aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/ngatm/netnatm
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ngatm/netnatm')
-rw-r--r--sys/contrib/ngatm/netnatm/addr.h42
-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.c1922
-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.h130
-rw-r--r--sys/contrib/ngatm/netnatm/genfiles15
-rw-r--r--sys/contrib/ngatm/netnatm/misc/straddr.c235
-rw-r--r--sys/contrib/ngatm/netnatm/misc/unimsg_common.c54
-rw-r--r--sys/contrib/ngatm/netnatm/msg/geniec.awk110
-rw-r--r--sys/contrib/ngatm/netnatm/msg/genieh.awk61
-rw-r--r--sys/contrib/ngatm/netnatm/msg/genmsgc.awk274
-rw-r--r--sys/contrib/ngatm/netnatm/msg/genmsgh.awk80
-rw-r--r--sys/contrib/ngatm/netnatm/msg/ie.def84
-rw-r--r--sys/contrib/ngatm/netnatm/msg/msg.def582
-rw-r--r--sys/contrib/ngatm/netnatm/msg/parseie.awk150
-rw-r--r--sys/contrib/ngatm/netnatm/msg/parsemsg.awk138
-rw-r--r--sys/contrib/ngatm/netnatm/msg/priv.h119
-rw-r--r--sys/contrib/ngatm/netnatm/msg/privmsg.c275
-rw-r--r--sys/contrib/ngatm/netnatm/msg/traffic.c406
-rw-r--r--sys/contrib/ngatm/netnatm/msg/uni_config.h70
-rw-r--r--sys/contrib/ngatm/netnatm/msg/uni_hdr.h220
-rw-r--r--sys/contrib/ngatm/netnatm/msg/uni_ie.c7166
-rw-r--r--sys/contrib/ngatm/netnatm/msg/uni_ie.h57
-rw-r--r--sys/contrib/ngatm/netnatm/msg/uni_ietab.h958
-rw-r--r--sys/contrib/ngatm/netnatm/msg/uni_msg.c4901
-rw-r--r--sys/contrib/ngatm/netnatm/msg/uni_msg.h342
-rw-r--r--sys/contrib/ngatm/netnatm/msg/unimsglib.h168
-rw-r--r--sys/contrib/ngatm/netnatm/msg/uniprint.h72
-rw-r--r--sys/contrib/ngatm/netnatm/msg/unistruct.h1371
-rw-r--r--sys/contrib/ngatm/netnatm/saal/saal_sscfu.c577
-rw-r--r--sys/contrib/ngatm/netnatm/saal/saal_sscop.c4946
-rw-r--r--sys/contrib/ngatm/netnatm/saal/sscfu.h103
-rw-r--r--sys/contrib/ngatm/netnatm/saal/sscfudef.h73
-rw-r--r--sys/contrib/ngatm/netnatm/saal/sscfupriv.h66
-rw-r--r--sys/contrib/ngatm/netnatm/saal/sscop.h126
-rw-r--r--sys/contrib/ngatm/netnatm/saal/sscopdef.h159
-rw-r--r--sys/contrib/ngatm/netnatm/saal/sscoppriv.h318
-rw-r--r--sys/contrib/ngatm/netnatm/sig/genmsgcpyc.awk80
-rw-r--r--sys/contrib/ngatm/netnatm/sig/genmsgcpyh.awk55
-rw-r--r--sys/contrib/ngatm/netnatm/sig/sig_call.c4310
-rw-r--r--sys/contrib/ngatm/netnatm/sig/sig_coord.c1171
-rw-r--r--sys/contrib/ngatm/netnatm/sig/sig_party.c1353
-rw-r--r--sys/contrib/ngatm/netnatm/sig/sig_print.c622
-rw-r--r--sys/contrib/ngatm/netnatm/sig/sig_reset.c827
-rw-r--r--sys/contrib/ngatm/netnatm/sig/sig_uni.c749
-rw-r--r--sys/contrib/ngatm/netnatm/sig/sig_unimsgcpy.c594
-rw-r--r--sys/contrib/ngatm/netnatm/sig/sig_verify.c442
-rw-r--r--sys/contrib/ngatm/netnatm/sig/uni.h106
-rw-r--r--sys/contrib/ngatm/netnatm/sig/unidef.h480
-rw-r--r--sys/contrib/ngatm/netnatm/sig/unimkmsg.h159
-rw-r--r--sys/contrib/ngatm/netnatm/sig/unimsgcpy.h113
-rw-r--r--sys/contrib/ngatm/netnatm/sig/unipriv.h563
-rw-r--r--sys/contrib/ngatm/netnatm/sig/unisig.h49
-rw-r--r--sys/contrib/ngatm/netnatm/unimsg.h92
61 files changed, 43486 insertions, 0 deletions
diff --git a/sys/contrib/ngatm/netnatm/addr.h b/sys/contrib/ngatm/netnatm/addr.h
new file mode 100644
index 000000000000..c1ba20eb1c3d
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/addr.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/addr.h,v 1.3 2004/07/08 08:21:45 brandt Exp $
+ */
+#ifndef _NETNATM_ADDR_H_
+#define _NETNATM_ADDR_H_
+
+int uni_str2nsap(u_char *, const char *);
+void uni_nsap2str(char *, const u_char *, int);
+
+void uni_prefix2str(char *, const u_char *, u_int, int);
+
+int uni_e1642nsap(u_char *, const char *);
+int uni_nsap2e164(char *, const u_char *, int);
+
+#endif
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..3350e2cb3806
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/api/cc_conn.c
@@ -0,0 +1,2096 @@
+/*
+ * Copyright (c) 2003-2007
+ * 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.
+ *
+ * $Id: cc_conn.c 1291 2007-07-10 10:35:38Z brandt_h $
+ *
+ * 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]);
+}
+
+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]);
+}
+
+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
+ */
+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
+ */
+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 op=%u", op);
+ 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);
+ }
+ }
+}
+
+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",
+ cc_conn_sigtab[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..245f8b7b5f04
--- /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.3 2004/08/05 07:10:56 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 <machine/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 = CCGETERRNO();
+ 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 = CCGETERRNO();
+ 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..75ce91eb4e56
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/api/cc_user.c
@@ -0,0 +1,1922 @@
+/*
+ * 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.3 2004/07/16 18:46:55 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 */
+ uni_msg_destroy(msg);
+ 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 */
+ uni_msg_destroy(msg);
+ 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;
+ uni_msg_destroy(msg);
+
+ if (newep == NULL) {
+ cc_user_err(user, ATMERR_BAD_ENDPOINT);
+ return;
+ }
+
+ if (newep->state != USER_NULL || newep->accepted != NULL) {
+ 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..c0f30750fc10
--- /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.
+ *
+ * $Begemot: libunimsg/netnatm/api/ccpriv.h,v 1.2 2005/05/23 11:49:17 brandt_h Exp $
+ *
+ * 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..ffbfc9fa42e8
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/api/unisap.h
@@ -0,0 +1,130 @@
+/*
+ * 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.6 2005/05/23 11:49:17 brandt_h Exp $
+ */
+#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
new file mode 100644
index 000000000000..70fb5e880463
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/genfiles
@@ -0,0 +1,15 @@
+#!/bin/sh
+# Copyright (c) 2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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
+awk -f ${SRC}msg/parsemsg.awk -f ${SRC}msg/genmsgh.awk ${SRC}msg/msg.def >${DST}msg/uni_msg.h
+awk -f ${SRC}msg/parsemsg.awk -f ${SRC}sig/genmsgcpyh.awk ${SRC}msg/msg.def >${DST}sig/unimsgcpy.h
+awk -f ${SRC}msg/parsemsg.awk -f ${SRC}sig/genmsgcpyc.awk ${SRC}msg/msg.def >${DST}sig/sig_unimsgcpy.c
diff --git a/sys/contrib/ngatm/netnatm/misc/straddr.c b/sys/contrib/ngatm/netnatm/misc/straddr.c
new file mode 100644
index 000000000000..7d21b8f74206
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/misc/straddr.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 1996-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/misc/straddr.c,v 1.4 2004/07/08 08:22:02 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/addr.h>
+
+/*
+ * Convert an NSAP address from the ASCII format to the binary.
+ * ASCII format means each byte formatted as a 2-byte hex number
+ * with dots freely interspersed between the bytes.
+ * If the conversion is succesful, the function returns 0, -1
+ * on conversion errors.
+ */
+int
+uni_str2nsap(u_char *out, const char *in)
+{
+ int i;
+ int c;
+
+ for(i = 0; i < 20; i++) {
+ while((c = *in++) == '.')
+ ;
+ if(!isascii(c) || !isxdigit(c))
+ return -1;
+ out[i] = isdigit(c) ? (c - '0')
+ : islower(c) ? (c - 'a' + 10)
+ : (c - 'A' + 10);
+ out[i] <<= 4;
+ c = *in++;
+ if(!isascii(c) || !isxdigit(c))
+ return -1;
+ out[i] |= isdigit(c) ? (c - '0')
+ : islower(c) ? (c - 'a' + 10)
+ : (c - 'A' + 10);
+ }
+ return *in != '\0';
+}
+
+/*
+ * Parse an emebedded E.164 NSAP address.
+ * If check is 0, the contents of the last 11 bytes are ignored
+ * If check is 1, the contents of all of these but the selector byte
+ * are checked to be zero. If check is 2 all 11 bytes must be 0.
+ */
+int
+uni_nsap2e164(char *e164, const u_char *nsap, int check)
+{
+ char *p = e164;
+ u_int d;
+ int i;
+
+ if(nsap[0] != 0x45)
+ return -1;
+ if((nsap[8] & 0xf) != 0xf)
+ return -1;
+ for(i = 1; i <= 7; i++) {
+ d = (nsap[i] >> 4) & 0xf;
+ if(d == 0x00 && p == e164)
+ continue;
+ if(d >= 0xa)
+ return -1;
+ *p++ = d + '0';
+
+ d = nsap[i] & 0xf;
+ if(d == 0x00 && p == e164)
+ continue;
+ if(d >= 0xa)
+ return -1;
+ *p++ = d + '0';
+ }
+ d = (nsap[i] >> 4) & 0xf;
+ if(d != 0x00 || p == e164) {
+ if(d >= 0xa)
+ return -1;
+ *p++ = d + '0';
+ }
+ if(p == e164)
+ return -1;
+ *p++ = 0;
+
+ if(check == 0)
+ return 0;
+ while(i < ((check == 1) ? 19 : 20)) {
+ if(nsap[i] != 0x00)
+ return -1;
+ i++;
+ }
+
+ return 0;
+}
+
+/*
+ * Convert a binary representation to ASCII. The standard formats are
+ * recognized and dotted. Non-standard formats get no dots altogether.
+ */
+void
+uni_prefix2str(char *out, const u_char *in, u_int len, int dotit)
+{
+ static char hex[16] = "0123456789abcdef";
+ static int fmt[3][6] = {
+ { 1, 2, 10, 6, 1, 0 },
+ { 1, 2, 10, 6, 1, 0 },
+ { 1, 8, 4, 6, 1, 0 },
+ };
+ int f, b;
+ u_int i;
+
+ if (len > 20)
+ len = 20;
+
+ if(dotit) {
+ switch(*in) {
+
+ case 0x39: /* DCC */
+ i = 0;
+ fmt:
+ for(f = 0; fmt[i][f]; f++) {
+ if (len == 0)
+ goto done;
+ if(f != 0)
+ *out++ = '.';
+ for(b = 0; b < fmt[i][f]; b++) {
+ if (len-- == 0)
+ goto done;
+ *out++ = hex[(*in >> 4) & 0xf];
+ *out++ = hex[*in & 0xf];
+ in++;
+ }
+ }
+ done:
+ *out = '\0';
+ return;
+
+ case 0x47: /* ICD */
+ i = 1;
+ goto fmt;
+
+ case 0x45: /* E.164 */
+ i = 2;
+ goto fmt;
+ }
+ }
+
+ /* undotted */
+ for(i = 0; i < len; i++) {
+ *out++ = hex[(*in >> 4) & 0xf];
+ *out++ = hex[*in & 0xf];
+ in++;
+ }
+ *out = '\0';
+}
+
+void
+uni_nsap2str(char *out, const u_char *in, int dotit)
+{
+ uni_prefix2str(out, in, 20, dotit);
+}
+
+/*
+ * Make an embedded E.164 NSAP address from a NSAP address.
+ * The E.164 address is a string of digits, at least one digit and
+ * not more than 15 digits long. The NSAP address will start with
+ * byte 0x45 and then a 8 byte field, which contains the right
+ * justified E.164 address in BCD coding, filled with a 0xf to the
+ * right. The rest of the address is zero.
+ * The function returns 0 if everything is ok, -1 in case of a wrong
+ * E.164 address.
+ */
+int
+uni_e1642nsap(u_char *nsap, const char *e164)
+{
+ size_t len;
+ int fill;
+ u_int i;
+
+ if((len = strlen(e164)) > 15 || len == 0)
+ return -1;
+ for(i = 0; i < len; i++)
+ if(!isdigit(e164[i]))
+ return -1;
+
+ *nsap++ = 0x45;
+ fill = (15 - len) / 2;
+ while(fill--)
+ *nsap++ = 0x00;
+ if((len & 1) == 0) {
+ *nsap++ = *e164++ - '0';
+ len--;
+ }
+ while(len > 1) {
+ len -= 2;
+ *nsap = (*e164++ - '0') << 4;
+ *nsap++ |= *e164 - '0';
+ }
+ *nsap++ = ((*e164++ - '0') << 4) | 0xf;
+ for(fill = 0; fill < 11; fill++)
+ *nsap++ = 0;
+
+ return 0;
+}
diff --git a/sys/contrib/ngatm/netnatm/misc/unimsg_common.c b/sys/contrib/ngatm/netnatm/misc/unimsg_common.c
new file mode 100644
index 000000000000..033213aef781
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/misc/unimsg_common.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2003-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/misc/unimsg_common.c,v 1.3 2004/07/08 08:22:03 brandt Exp $
+ */
+
+#include <netnatm/unimsg.h>
+
+/*
+ * Make sure there is enough space in front of the data for
+ * len bytes, and update the read pointer.
+ */
+int
+uni_msg_prepend(struct uni_msg *msg, size_t len)
+{
+ size_t need;
+
+ if (uni_msg_leading(msg) >= len) {
+ msg->b_rptr -= len;
+ return (0);
+ }
+ need = len - uni_msg_leading(msg);
+ if (uni_msg_ensure(msg, need))
+ return (-1);
+ memcpy(msg->b_rptr + need, msg->b_rptr, uni_msg_len(msg));
+ msg->b_rptr += need - len;
+ msg->b_wptr += need;
+ return (0);
+}
diff --git a/sys/contrib/ngatm/netnatm/msg/geniec.awk b/sys/contrib/ngatm/netnatm/msg/geniec.awk
new file mode 100644
index 000000000000..d0620825178f
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/geniec.awk
@@ -0,0 +1,110 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/msg/geniec.awk,v 1.4 2003/10/10 14:50:05 hbb Exp $
+#
+# Generate table for IE parsing.
+#
+# This function is called before the first line
+#
+function begin() {
+ for(i = 0; i < 256; i++) {
+ for(j = 0; j < 4; j++) {
+ decl[i,j] = ""
+ }
+ }
+}
+
+#
+# This function is called after the last line.
+#
+function end() {
+ print ""
+ print "const struct iedecl *uni_ietable[256][4] = {"
+ for(i = 0; i < 256; i++) {
+ printf "\t{"
+ for(j = 0; j < 4; j++) {
+ if(decl[i,j] == "") {
+ printf " NULL,"
+ } else {
+ printf " &%s,", decl[i,j]
+ }
+ }
+ printf " }, /* 0x%02x */\n", i
+ }
+ print "};"
+}
+
+#
+# This function is called just when the first information element was found
+#
+function first_element() {
+ print "/* This file was created automatically"
+ print " * Source file: " id
+ print " */"
+ print ""
+}
+
+#
+# This is called, when the information element is defaulted (there is
+# only the name and the coding scheme
+#
+function element_default() {
+ print ""
+ print "static const struct iedecl decl_" coding "_" ie " = {"
+ print "\tUNIFL_DEFAULT,"
+ print "\t0,"
+ print "\t(uni_print_f)NULL,"
+ print "\t(uni_check_f)NULL,"
+ print "\t(uni_encode_f)NULL,"
+ print "\t(uni_decode_f)NULL"
+ print "};"
+ decl[number,ncoding] = "decl_" coding "_" ie
+}
+
+#
+# This is found for a real, non-default IE
+#
+function element() {
+ print ""
+ print "static void uni_ie_print_" coding "_" ie "(struct uni_ie_" ie " *, struct unicx *);"
+ print "static int uni_ie_check_" coding "_" ie "(struct uni_ie_" ie " *, struct unicx *);"
+ print "static int uni_ie_encode_" coding "_" ie "(struct uni_msg *, struct uni_ie_" ie " *, struct unicx *);"
+ print "static int uni_ie_decode_" coding "_" ie "(struct uni_ie_" ie " *, struct uni_msg *, u_int, struct unicx *);"
+ print ""
+ print "static struct iedecl decl_" coding "_" ie " = {"
+ if(access) print "\tUNIFL_ACCESS,"
+ else print "\t0,"
+ print "\t" len ","
+ print "\t(uni_print_f)uni_ie_print_" coding "_" ie ","
+ print "\t(uni_check_f)uni_ie_check_" coding "_" ie ","
+ print "\t(uni_encode_f)uni_ie_encode_" coding "_" ie ","
+ print "\t(uni_decode_f)uni_ie_decode_" coding "_" ie ""
+ print "};"
+ decl[number,ncoding] = "decl_" coding "_" ie
+}
diff --git a/sys/contrib/ngatm/netnatm/msg/genieh.awk b/sys/contrib/ngatm/netnatm/msg/genieh.awk
new file mode 100644
index 000000000000..7120d7b9a020
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/genieh.awk
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/msg/genieh.awk,v 1.4 2004/07/08 08:22:03 brandt Exp $
+#
+# Generate IE header file
+#
+function begin() {
+}
+
+function first_element() {
+ print "/* This file was created automatically"
+ print " * Source file: " id
+ print " */"
+ print ""
+ print "#ifndef _NETNATM_MSG_UNI_IE_H_"
+ print "#define _NETNATM_MSG_UNI_IE_H_"
+ print ""
+ print "union uni_ieall {"
+ print " struct uni_iehdr h;"
+}
+
+function end() {
+ print "};"
+ print ""
+ print "#endif"
+}
+
+function element_default() {
+}
+
+function element() {
+ if(ie in u) return
+ u[ie] = 1
+ print " struct uni_ie_" ie " " ie ";"
+}
diff --git a/sys/contrib/ngatm/netnatm/msg/genmsgc.awk b/sys/contrib/ngatm/netnatm/msg/genmsgc.awk
new file mode 100644
index 000000000000..ffd69ac5fc69
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/genmsgc.awk
@@ -0,0 +1,274 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/msg/genmsgc.awk,v 1.6 2004/07/08 08:22:04 brandt Exp $
+#
+# Generate message functions.
+#
+function begin() {
+}
+
+function first_entry() {
+ print "/* This file was created automatically"
+ print " * Source file: " id
+ print " */"
+ print ""
+ print "#include <sys/types.h>"
+ print "#include <sys/param.h>"
+ print ""
+ print "#ifdef _KERNEL"
+ print "#include <sys/libkern.h>"
+ print "#else"
+ print "#include <string.h>"
+ print "#endif"
+ print "#include <netnatm/unimsg.h>"
+ print "#include <netnatm/msg/unistruct.h>"
+ print "#include <netnatm/msg/unimsglib.h>"
+ print "#include <netnatm/msg/priv.h>"
+ print "#include <netnatm/msg/privmsg.c>"
+}
+
+function end() {
+ print ""
+ print "const struct msgdecl *uni_msgtable[256] = {"
+ for(i = 0; i < 256; i++) {
+ if(decl[i] == "") {
+ printf "\t&decl_unknown,"
+ } else {
+ printf "\t&%s,", decl[i]
+ }
+ printf "\t/* 0x%02x */\n", i
+ }
+ print "};"
+}
+
+function start_message() {
+}
+
+function end_message() {
+ gen_print()
+ gen_check()
+ gen_encode()
+ gen_decode()
+ gen_reg()
+}
+
+function gen_print() {
+ print ""
+ print "static void"
+ print "print_" msg "(struct uni_" msg " *msg, struct unicx *cx)"
+ print "{"
+ if(msgrep) {
+ print "\tu_int i;"
+ print ""
+ }
+ for(i = 0; i < cnt; i++) {
+ ie = iename[i]
+ uie = toupper(iename[i])
+ if(ierep[i]) {
+ print "\tif(msg->" ie "_repeat.h.present & UNI_IE_PRESENT)"
+ print "\t\tuni_print_ie_internal(UNI_IE_REPEAT, (union uni_ieall *)&msg->" ie "_repeat, cx);"
+ }
+ if(ienum[i] == "-") {
+ print "\tif(msg->" ie ".h.present & UNI_IE_PRESENT)"
+ print "\t\tuni_print_ie_internal(UNI_IE_" uie ", (union uni_ieall *)&msg->" ie ", cx);"
+ } else {
+ print "\tfor(i = 0; i < " ienum[i] "; i++)"
+ print "\t\tif(msg->" ie "[i].h.present & UNI_IE_PRESENT)"
+ print "\t\t\tuni_print_ie_internal(UNI_IE_" uie ", (union uni_ieall *)&msg->" ie "[i], cx);"
+ }
+ }
+ print "}"
+}
+
+function gen_check() {
+ print ""
+ print "static int"
+ print "check_" msg "(struct uni_" msg " *m, struct unicx *cx)"
+ print "{"
+ print "\tint ret = 0;"
+ if(msgrep) {
+ print "\tu_int i;"
+ }
+ print ""
+ for(i = 0; i < cnt; i++) {
+ ie = iename[i]
+ if(ierep[i]) {
+ if(iecond[i] == "1") {
+ print "\tret |= uni_check_ie(UNI_IE_REPEAT, (union uni_ieall *)&m->" ie "_repeat, cx);"
+ } else {
+ print "\tif(!(" iecond[i] "))"
+ print "\t\tret |= IE_ISPRESENT(m->" ie "_repeat);"
+ print "\telse"
+ print "\t\tret |= uni_check_ie(UNI_IE_REPEAT, (union uni_ieall *)&m->" ie "_repeat, cx);"
+ }
+ }
+ if(ienum[i] == "-") {
+ if(iecond[i] == "1") {
+ print "\tret |= uni_check_ie(UNI_IE_" toupper(ie) ", (union uni_ieall *)&m->" ie ", cx);"
+ } else {
+ print "\tif(!(" iecond[i] "))"
+ print "\t\tret |= IE_ISPRESENT(m->" ie ");"
+ print "\telse"
+ print "\t\tret |= uni_check_ie(UNI_IE_" toupper(ie) ", (union uni_ieall *)&m->" ie ", cx);"
+ }
+ } else {
+ print "\tfor(i = 0; i < " ienum[i]" ; i++) {"
+ if(iecond[i] == "1") {
+ print "\t\tret |= uni_check_ie(UNI_IE_" toupper(ie) ", (union uni_ieall *)&m->" ie "[i], cx);"
+ } else {
+ print "\t\tif(!(" iecond[i] "))"
+ print "\t\t\tret |= IE_ISPRESENT(m->" ie "[i]);"
+ print "\t\telse"
+ print "\t\t\tret |= uni_check_ie(UNI_IE_" toupper(ie) ", (union uni_ieall *)&m->" ie "[i], cx);"
+ }
+ print "\t}"
+ }
+ }
+ print ""
+ print "\treturn ret;"
+ print "}"
+}
+
+function gen_encode() {
+ print ""
+ print "static int"
+ print "encode_" msg "(struct uni_msg *msg, struct uni_" msg " *p, struct unicx *cx)"
+ print "{"
+ print "\tu_int mlen;"
+ if(msgrep) {
+ print "\tu_int i;"
+ }
+ print ""
+ print "\tif(uni_encode_msg_hdr(msg, &p->hdr, UNI_" toupper(msg) ", cx, &mlen))"
+ print "\t\treturn (-2);"
+ print ""
+ for(i = 0; i < cnt; i++) {
+ ie = iename[i]
+ if(ierep[i]) {
+ print "\tif((p->" ie "_repeat.h.present & UNI_IE_PRESENT) &&"
+ print "\t uni_encode_ie(UNI_IE_" toupper(ie) ", msg, (union uni_ieall *)&p->" ie "_repeat, cx))"
+ print "\t\treturn (0x10000000 + UNI_IE_" toupper(ie) ");"
+ }
+ if(ienum[i] == "-") {
+ print "\tif((p->" ie ".h.present & UNI_IE_PRESENT) &&"
+ print "\t uni_encode_ie(UNI_IE_" toupper(ie) ", msg, (union uni_ieall *)&p->" ie ", cx))"
+ print "\t\treturn (UNI_IE_" toupper(ie) ");"
+ } else {
+ print "\tfor(i = 0; i < " ienum[i] "; i++)"
+ print "\t\tif((p->" ie "[i].h.present & UNI_IE_PRESENT) &&"
+ print "\t\t uni_encode_ie(UNI_IE_" toupper(ie) ", msg, (union uni_ieall *)&p->" ie "[i], cx))"
+ print "\t\treturn ((i << 16) + UNI_IE_" toupper(ie) ");"
+ }
+ }
+ print ""
+ print "\tmsg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;"
+ print "\tmsg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;"
+ print ""
+ print "\treturn (0);"
+ print "}"
+}
+
+function gen_decode() {
+ print ""
+ print "static int"
+ print "decode_" msg "(struct uni_" msg " *out, struct uni_msg *msg,"
+ print " enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,"
+ print " struct unicx *cx)"
+ print "{"
+ if (msgrep) {
+ print " u_int i;"
+ print ""
+ }
+ print " switch (ie) {"
+
+ rep=0
+ for (i = 0; i < cnt; i++) {
+ ie = iename[i]
+ print ""
+ print " case UNI_IE_" toupper(ie) ":"
+ if (iecond[i] != "1") {
+ print " if (!(" iecond[i] "))"
+ print " return (DEC_ILL);"
+ }
+ if (ierep[i]) {
+ rep=1
+ print " if (IE_ISPRESENT(cx->repeat))"
+ print " out->" ie "_repeat = cx->repeat;"
+ }
+ if (ienum[i] == "-") {
+ print " out->" ie ".h = *hdr;"
+ print " if (hdr->present & UNI_IE_ERROR)"
+ print " return (DEC_ERR);"
+ print " if(uni_decode_ie_body(UNI_IE_"toupper(ie)", (union uni_ieall *)&out->"ie", msg, ielen, cx))"
+ print " return (DEC_ERR);"
+
+ } else {
+ print " for(i = 0; i < " ienum[i] "; i++)"
+ print " if (!IE_ISPRESENT(out->" ie "[i])) {"
+ print " out->" ie "[i].h = *hdr;"
+ print " if (hdr->present & UNI_IE_ERROR)"
+ print " return (DEC_ERR);"
+ print " if(uni_decode_ie_body(UNI_IE_"toupper(ie)", (union uni_ieall *)&out->"ie"[i], msg, ielen, cx))"
+ print " return (DEC_ERR);"
+ print " break;"
+ print " }"
+ }
+ print " break;"
+ }
+ if(rep) {
+ print ""
+ print " case UNI_IE_REPEAT:"
+ print " cx->repeat.h = *hdr;"
+ print " if (hdr->present & UNI_IE_ERROR)"
+ print " return (DEC_ERR);"
+ print " if (uni_decode_ie_body(UNI_IE_REPEAT, (union uni_ieall *)&cx->repeat, msg, ielen, cx))"
+ print " return (DEC_ERR);"
+ print " break;"
+ }
+
+ print ""
+ print " default:"
+ print " return (DEC_ILL);"
+ print " }"
+ print " return (DEC_OK);"
+ print "}"
+}
+
+function gen_reg() {
+ print ""
+ print "static const struct msgdecl decl_" msg " = {"
+ print "\t0,"
+ print "\t\"" msg "\","
+ print "\t(uni_msg_print_f)print_" msg ","
+ print "\t(uni_msg_check_f)check_" msg ","
+ print "\t(uni_msg_encode_f)encode_" msg ","
+ print "\t(uni_msg_decode_f)decode_" msg
+ print "};"
+ decl[code] = "decl_" msg
+}
diff --git a/sys/contrib/ngatm/netnatm/msg/genmsgh.awk b/sys/contrib/ngatm/netnatm/msg/genmsgh.awk
new file mode 100644
index 000000000000..8705b31e1e30
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/genmsgh.awk
@@ -0,0 +1,80 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/msg/genmsgh.awk,v 1.4 2004/07/08 08:22:04 brandt Exp $
+#
+# Generate message header
+#
+function begin() {
+}
+
+function first_entry() {
+ print "/* This file was created automatically"
+ print " * Source file: " id
+ print " */"
+ print ""
+ print "#ifndef _NETNATM_MSG_UNI_MSG_H_"
+ print "#define _NETNATM_MSG_UNI_MSG_H_"
+}
+
+function end() {
+ print ""
+ print "union uni_msgall {"
+ print "\tstruct uni_msghdr\thdr;"
+ for(i = 0; i < mcnt; i++) {
+ m = messages[i]
+ if(msgcond[i] == "") {
+ print "\tstruct uni_" m "\t" m ";"
+ } else {
+ print "\tstruct uni_" m "\t" m ";\t/* " msgcond[i] " */"
+ }
+ }
+ print "};"
+ print ""
+ print "#endif"
+}
+
+function start_message() {
+}
+
+function end_message() {
+ print ""
+ print "struct uni_" msg " {"
+ print "\tstruct uni_msghdr\thdr;"
+ for(i = 0; i < cnt; i++) {
+ if(ierep[i]) {
+ print "\tstruct uni_ie_repeat\t" iename[i] "_repeat;"
+ }
+ if(ienum[i] != "-") {
+ print "\tstruct uni_ie_" iename[i] "\t" iename[i] "[" ienum[i] "];"
+ } else {
+ print "\tstruct uni_ie_" iename[i] "\t" iename[i] ";"
+ }
+ }
+ print "};"
+}
diff --git a/sys/contrib/ngatm/netnatm/msg/ie.def b/sys/contrib/ngatm/netnatm/msg/ie.def
new file mode 100644
index 000000000000..fbeabe87a84c
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/ie.def
@@ -0,0 +1,84 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/msg/ie.def,v 1.4 2003/09/29 10:47:18 hbb Exp $
+#
+# Define information elements --- no content definition
+#
+#########################################################################
+element cause 0x08 itu 34
+element cause 0x08 net 34
+element callstate 0x14 itu 5
+element facility 0x1c itu UNI_FACILITY_MAXAPDU+1+4 q2932
+element notify 0x27 itu UNI_NOTIFY_MAXLEN+4
+element eetd 0x42 itu 11
+element eetd 0x42 net 13
+element conned 0x4c itu 25 file=addr
+element connedsub 0x4d itu 25 access file=addr
+element epref 0x54 itu 7
+element epstate 0x55 itu 5
+element aal 0x58 itu 21 access
+element traffic 0x59 itu 30
+element traffic 0x59 net
+element connid 0x5a itu 9
+element qos 0x5c itu 6
+element qos 0x5c net 6
+element bhli 0x5d itu 13 access
+element bearer 0x5e itu 7
+element blli 0x5f itu 17 access
+element lshift 0x60 itu 5 0 file=shift
+element nlshift 0x61 itu 5 0 file=shift
+element scompl 0x62 itu 5 !pnni
+element repeat 0x63 itu 5
+element calling 0x6c itu 26 file=addr
+element callingsub 0x6d itu 25 access file=addr
+element called 0x70 itu 25 file=addr
+element calledsub 0x71 itu 25 access file=addr
+element tns 0x78 itu 9
+element tns 0x78 net
+element restart 0x79 itu 5
+element uu 0x7e itu UNI_UU_MAXLEN+4 access !pnni
+element git 0x7f net 33
+element mintraffic 0x81 itu 20 file=traffic
+element mintraffic 0x81 net
+element atraffic 0x82 itu 30 file=traffic
+element atraffic 0x82 net
+element abrsetup 0x84 net 36 file=abr
+element report 0x89 itu 5
+element called_soft 0xe0 net 11 file=soft pnni
+element crankback 0xe1 net 72 pnni
+element dtl 0xe2 net UNI_DTL_LOGNP_SIZE*UNI_DTL_MAXNUM+6 pnni
+element calling_soft 0xe3 net 10 file=soft pnni
+element abradd 0xe4 net 14 file=abr
+element lij_callid 0xe8 net 9 file=lij !pnni
+element lij_param 0xe9 net 5 file=lij !pnni
+element lij_seqno 0xea net 8 file=lij !pnni
+element cscope 0xeb net 6
+element exqos 0xec net 25
+element mdcr 0xf0 net 13 file=traffic
+element unrec 0xfe itu 128
diff --git a/sys/contrib/ngatm/netnatm/msg/msg.def b/sys/contrib/ngatm/netnatm/msg/msg.def
new file mode 100644
index 000000000000..41453ec6a5c4
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/msg.def
@@ -0,0 +1,582 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/msg/msg.def,v 1.4 2003/09/29 10:47:18 hbb Exp $
+#
+# Define message contents
+#
+#########################################################################
+#
+# ALERTING message
+#
+# References:
+# Q.2931 8, 17*
+# ...A4 4, 11*
+# Q.2957 3
+# Q.2971 6
+# UNI4.0 5
+# PNNI1.0 177...178, 184*
+#
+# Notes:
+# N-ISDN compatiblity not implemented.
+#
+start alerting 0x01
+ connid - !pnni
+ epref
+ notify
+ git UNI_NUM_IE_GIT
+ uu - !pnni
+ report - !pnni
+ unrec
+end
+
+#########################################################################
+#
+# CALL PROCEEDING message
+#
+# References:
+# Q.2931 9, 18*
+# Q.2971 6
+# UNI4.0 5
+# PNNI1.0 178
+#
+# Notes:
+# N-ISDN compatiblity not implemented.
+#
+start call_proc 0x02
+ connid
+ epref
+ notify - !pnni
+ unrec
+end
+
+#########################################################################
+#
+# CONNECT message
+#
+# References:
+# Q.2931 p. 10, 19*
+# ...A4 6, 12*
+# Q.2932.1 p. 17
+# Q.2951 p. 30
+# Q.2957 p. 4
+# Q.2962 p. 3
+# Q.2971 p. 7
+# UNI4.0 p. 5-6, 61, 68, 77
+# PNNI1.0 pp. 178...179, 184...185*
+#
+# Notes:
+# N-ISDN compatiblity not implemented.
+#
+start connect 0x07
+ aal
+ blli
+ connid - !pnni
+ epref
+ notify
+ conned
+ connedsub
+ eetd
+ git UNI_NUM_IE_GIT
+ uu - !pnni
+ traffic
+ exqos
+ facility - q2932
+ abrsetup
+ abradd
+ called_soft - pnni
+ report - !pnni
+ unrec
+end
+
+#########################################################################
+#
+# CONNECT ACKNOWLEDGE message
+#
+# References:
+# Q.2931 11
+#
+start connect_ack 0x0f !pnni
+ notify
+ unrec
+end
+
+#########################################################################
+#
+# RELEASE message
+#
+# References:
+# Q.2931 p. 11, 22*
+# Q.2932.1 p. 18
+# Q.2957 p. 4
+# Q.2962 p. 3
+# UNI4.0 p. 6
+# PNNI1.0 pp. 179...180, 185...186*
+#
+# Notes:
+# N-ISDN compatiblity not implemented.
+#
+start release 0x4d
+ cause 2
+ notify
+ git UNI_NUM_IE_GIT
+ uu - !pnni
+ facility - q2932
+ crankback - pnni
+ unrec
+end
+
+#########################################################################
+#
+# RELEASE COMPLETE message
+#
+# References:
+# Q.2931 p. 12
+# UNI4.0 p. 6
+# PNNI1.0 p. 180
+#
+start release_compl 0x5a
+ cause 2
+ git UNI_NUM_IE_GIT !pnni
+ uu - !pnni
+ crankback - pnni
+ unrec
+end
+
+#########################################################################
+#
+# SETUP message
+#
+# References:
+# Q.2931 13-14, 23-24*
+# ...A4 7-9, 13-16*
+# Q.2957 5
+# Q.2962 3
+# Q.2971 7
+# UNI4.0 6-7, 43, 57*, 60-61, 68-69, 78
+# PNNI1.0 180...182, 186*
+# af-cs-0147.000
+#
+# Notes:
+#
+start setup 0x05
+ aal
+ traffic
+ bearer
+ bhli
+ blli UNI_NUM_IE_BLLI/R
+ called
+ calledsub UNI_NUM_IE_CALLEDSUB
+ calling
+ callingsub UNI_NUM_IE_CALLINGSUB
+ connid
+ qos
+ eetd
+ notify
+ scompl - !pnni
+ tns UNI_NUM_IE_TNS
+ epref
+ atraffic
+ mintraffic
+ uu - !pnni
+ git UNI_NUM_IE_GIT
+ lij_callid - !pnni
+ lij_param - !pnni
+ lij_seqno - !pnni
+ exqos
+ abrsetup
+ abradd
+ cscope
+ calling_soft - pnni
+ called_soft - pnni
+ dtl UNI_NUM_IE_DTL/R pnni
+ report - !pnni
+ mdcr
+ unrec
+end
+
+#########################################################################
+#
+# STATUS message
+#
+# References:
+# Q.2931 p. 14
+# Q.2971 p. 8
+# PNNI1.0 p. 182
+#
+start status 0x7d
+ callstate
+ cause
+ epref
+ epstate
+ unrec
+end
+
+#########################################################################
+#
+# STATUS ENQUIRY message
+#
+# References:
+# Q.2931 p. 15
+# Q.2971 p. 8
+# PNNI1.0 pp. 182...183
+#
+start status_enq 0x75
+ epref
+ unrec
+end
+
+#########################################################################
+#
+# NOTIFY message
+#
+# References:
+# Q.2931 p. 15
+# Q.2971 p. 8
+# PNNI1.0 p. 183
+#
+start notify 0x6e
+ notify
+ epref
+ unrec
+end
+
+#########################################################################
+#
+# RESTART message
+#
+# References:
+# Q.2931 p. 26
+# UNI4.0 p. 7
+# PNNI1.0 pp. 186...187
+#
+start restart 0x46
+ connid
+ restart
+ unrec
+end
+
+#########################################################################
+#
+# RESTART ACKNOWLEDGE message
+#
+# References:
+# Q.2931 p. 26
+# UNI4.0 p. 7
+# PNNI1.0 p. 187
+#
+start restart_ack 0x4e
+ connid
+ restart
+ unrec
+end
+
+#########################################################################
+#
+# ADD PARTY message
+#
+# References:
+# Q.2971 10, 47
+# UNI4.0 39, 43-44
+# PNNI1.0 188...189
+#
+# Notes:
+#
+start add_party 0x80
+ aal
+ bhli
+ blli
+ called
+ calledsub UNI_NUM_IE_CALLEDSUB
+ calling
+ callingsub UNI_NUM_IE_CALLINGSUB
+ scompl - !pnni
+ tns UNI_NUM_IE_TNS
+ epref
+ notify
+ eetd
+ uu - !pnni
+ git UNI_NUM_IE_GIT
+ lij_seqno - !pnni
+ calling_soft - pnni
+ called_soft - pnni
+ dtl UNI_NUM_IE_DTL/R pnni
+ unrec
+end
+
+#########################################################################
+#
+# ADD PARTY ACKNOWLEDGE message
+#
+# References:
+# Q.2971 10, 42, 47
+# UNI4.0 39
+# PNNI1.0 189
+#
+# Notes:
+#
+start add_party_ack 0x81
+ epref
+ aal
+ blli
+ notify
+ eetd
+ conned
+ connedsub
+ uu - !pnni
+ git UNI_NUM_IE_GIT
+ called_soft - pnni
+ unrec
+end
+
+#########################################################################
+#
+# PARTY ALERTING message
+#
+# References:
+# Q.2971 12, 49
+# UNI4.0 39
+# PNNI1.0 189...190
+#
+# Notes:
+#
+start party_alerting 0x85
+ epref
+ notify
+ uu - !pnni
+ git UNI_NUM_IE_GIT
+ unrec
+end
+
+#########################################################################
+#
+# ADD PARTY REJECT message
+#
+# References:
+# Q.2971 12, 48
+# UNI4.0 40
+# PNNI1.0 190
+#
+# Notes:
+#
+start add_party_rej 0x82
+ cause
+ epref
+ uu - !pnni
+ git UNI_NUM_IE_GIT
+ crankback - pnni
+ unrec
+end
+
+#########################################################################
+#
+# DROP PARTY message
+#
+# References:
+# Q.2971 13, 48
+# UNI4.0 40
+# PNNI1.0 191
+#
+# Notes:
+#
+start drop_party 0x83
+ cause
+ epref
+ notify
+ uu - !pnni
+ git UNI_NUM_IE_GIT
+ unrec
+end
+
+#########################################################################
+#
+# DROP PARTY ACKNOWLEDGE message
+#
+# References:
+# Q.2971 13, 49
+# UNI4.0 40
+# PNNI1.0 191
+#
+# Notes:
+#
+start drop_party_ack 0x84
+ epref
+ cause
+ uu - !pnni
+ git UNI_NUM_IE_GIT
+ unrec
+end
+
+#########################################################################
+#
+# LEAF SETUP REQUEST message
+#
+# References:
+# UNI4.0 45...46
+#
+# Notes:
+#
+start leaf_setup_req 0x91 !pnni
+ tns UNI_NUM_IE_TNS
+ calling
+ callingsub UNI_NUM_IE_CALLINGSUB
+ called
+ calledsub UNI_NUM_IE_CALLEDSUB
+ lij_callid
+ lij_seqno
+ unrec
+end
+
+#########################################################################
+#
+# LEAF SETUP FAIL message
+#
+# References:
+# UNI4.0 45...46
+#
+# Notes:
+#
+start leaf_setup_fail 0x90 !pnni
+ cause
+ called
+ calledsub
+ lij_seqno
+ tns UNI_NUM_IE_TNS
+ unrec
+end
+
+#########################################################################
+#
+# CO-BI SETUP message
+#
+# References:
+# Q.2932.1 16
+#
+# Notes:
+#
+start cobisetup 0x15 !pnni&&q2932
+ facility
+ called
+ calledsub
+ calling
+ notify
+ unrec
+end
+
+#########################################################################
+#
+# FACILITY message
+#
+# References:
+# Q.2932.1 14...15
+#
+# Notes:
+#
+start facility 0x62 !pnni&&q2932
+ facility
+ called
+ calledsub
+ calling
+ notify
+ unrec
+end
+
+#########################################################################
+#
+# MODIFY REQUEST message
+#
+# References:
+# Q.2963.1 p. 6
+# Q.2963.4 p. 4
+# UNI4.0-MFY p. 3
+#
+start modify_req 0x88 !pnni
+ traffic
+ atraffic
+ mintraffic
+ notify
+ git UNI_NUM_IE_GIT
+ unrec
+end
+
+#########################################################################
+#
+# MODIFY ACKNOWLEDGE message
+#
+# References:
+# Q.2963.1 p.6
+# Q.2963.3 p.5
+# UNI4.0-MFY p.3
+#
+start modify_ack 0x89 !pnni
+ report
+ traffic
+ notify
+ git UNI_NUM_IE_GIT
+ unrec
+end
+
+#########################################################################
+#
+# MODIFY REJECT message
+#
+# References:
+# Q.2963 p.6
+# UNI4.0-MFY p.3
+#
+start modify_rej 0x8a !pnni
+ cause
+ notify
+ git UNI_NUM_IE_GIT
+ unrec
+end
+
+#########################################################################
+#
+# CONNECTION AVAILABLE message
+#
+# References:
+# Q.2931A4 9...10
+# Q.2963 p.6
+# UNI4.0-MFY p.3
+#
+start conn_avail 0x8b !pnni
+ notify
+ git UNI_NUM_IE_GIT
+ report
+ unrec
+end
+
+#########################################################################
+#
+# UNKNOWN message
+#
+start unknown 0x100
+ epref
+ unrec
+end
diff --git a/sys/contrib/ngatm/netnatm/msg/parseie.awk b/sys/contrib/ngatm/netnatm/msg/parseie.awk
new file mode 100644
index 000000000000..14bd0f876978
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/parseie.awk
@@ -0,0 +1,150 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/msg/parseie.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $
+#
+# Parse the IE definition file
+#
+match($0, "Begemot:")!=0 {
+ gsub("^[^$]*", "")
+ gsub("[^$]*$", "")
+ id = $0
+ next
+}
+
+/^#/ {
+ next
+}
+NF == 0 {
+ next
+}
+
+BEGIN {
+ iecnt = 0
+ id = " * ???"
+ begin()
+}
+
+END {
+ end()
+}
+
+#
+# Syntax is:
+# element <name> <code> <coding> [<maxlen> [<options>*]]
+#
+$1=="element" {
+ if(iecnt == 0) first_element()
+ if(NF < 4) {
+ error("Bad number of args: " $0)
+ }
+ ie = $2
+ file = $2
+ number = parse_hex($3)
+ coding = $4
+ if(coding == "itu") {
+ ncoding = 0
+ } else if(coding == "net") {
+ ncoding = 3
+ } else {
+ error("bad coding " coding)
+ }
+ if(NF == 4) {
+ element_default()
+ file=""
+ } else {
+ len = $5
+ parse_options()
+ element()
+ }
+ ies[iecnt] = ie
+ codings[iecnt] = coding
+ files[iecnt] = file
+ iecnt++
+ next
+}
+
+{
+ error("Bad line: " $0)
+}
+
+function parse_options() {
+ access = 0
+ cond = ""
+ for(i = 6; i <= NF; i++) {
+ if($i == "access") {
+ access = 1
+ } else if($i == "-") {
+ } else if(index($i, "file=") == 1) {
+ file=substr($i, 6)
+ } else {
+ if(cond != "") {
+ error("Too many conditions: "$0)
+ }
+ cond = $i
+ }
+ }
+}
+
+function parse_hex(str, n)
+{
+ n = 0
+ if(substr(str,1,2) != "0x") {
+ error("bad hex number" str)
+ }
+ for(i = 3; i <= length(str); i++) {
+ c = substr(str,i,1)
+ if(match(c,"[0-9]") != 0) {
+ n = 16 * n + c
+ } else if(match(c,"[a-f]")) {
+ if(c == "a") n = 16 * n + 10
+ if(c == "b") n = 16 * n + 11
+ if(c == "c") n = 16 * n + 12
+ if(c == "d") n = 16 * n + 13
+ if(c == "e") n = 16 * n + 14
+ if(c == "f") n = 16 * n + 15
+ } else if(match(c,"[A-F]")) {
+ if(c == "A") n = 16 * n + 10
+ if(c == "B") n = 16 * n + 11
+ if(c == "C") n = 16 * n + 12
+ if(c == "D") n = 16 * n + 13
+ if(c == "E") n = 16 * n + 14
+ if(c == "F") n = 16 * n + 15
+ } else {
+ error("bad hex digit '" c "'")
+ }
+ }
+ return n
+}
+
+# function error(str)
+# {
+# print "error:" str >"/dev/stderr"
+# exit 1
+# }
+
diff --git a/sys/contrib/ngatm/netnatm/msg/parsemsg.awk b/sys/contrib/ngatm/netnatm/msg/parsemsg.awk
new file mode 100644
index 000000000000..ff13874d4509
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/parsemsg.awk
@@ -0,0 +1,138 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/msg/parsemsg.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $
+#
+# Parse the message definition file
+#
+match($0, "Begemot:")!=0 {
+ gsub("^[^$]*", "")
+ gsub("[^$]*$", "")
+ id = $0
+ next
+}
+
+/^#/ {
+ next
+}
+NF == 0 {
+ next
+}
+BEGIN {
+ state=0
+ id = " * ???"
+ mcnt=0
+ begin()
+}
+END {
+ end()
+}
+
+state==0 && $1=="start" {
+ if(NF < 3) error("bad number of fields in message start "$0)
+ state = 1
+ msg = $2
+ code = parse_hex($3)
+ messages[mcnt] = msg
+ msgcond[mcnt] = $4
+ msgrep = 0
+ msgrepie = 0
+ cnt = 0
+ if(mcnt == 0) first_entry()
+ start_message()
+ next
+}
+
+state==1 && $1=="end" {
+ state=0
+ mcnt++
+ end_message()
+ next
+}
+state==1 {
+ iename[cnt]=$1
+ if($2 == "") $2="-"
+ if(match($2, "[A-Za-z][A-Za-z0-9_]*/R") == 1) {
+ ienum[cnt]=substr($2, 1, length($2)-2)
+ ierep[cnt]=1
+ msgrepie=1
+ } else {
+ ierep[cnt]=0
+ ienum[cnt]=$2
+ }
+ if(ienum[cnt] != "-") msgrep = 1
+ if($3 == "" || $3 == "-") {
+ $3 = "1"
+ } else {
+ gsub("[a-zA-Z][a-zA-Z0-9]*", "cx->&", $3)
+ }
+ iecond[cnt] = $3
+ cnt++
+ next
+}
+
+{
+ error("bad line: "$0)
+}
+
+function parse_hex(str, n)
+{
+ n = 0
+ if(substr(str,1,2) != "0x") {
+ error("bad hex number" str)
+ }
+ for(i = 3; i <= length(str); i++) {
+ c = substr(str,i,1)
+ if(match(c,"[0-9]") != 0) {
+ n = 16 * n + c
+ } else if(match(c,"[a-f]")) {
+ if(c == "a") n = 16 * n + 10
+ if(c == "b") n = 16 * n + 11
+ if(c == "c") n = 16 * n + 12
+ if(c == "d") n = 16 * n + 13
+ if(c == "e") n = 16 * n + 14
+ if(c == "f") n = 16 * n + 15
+ } else if(match(c,"[A-F]")) {
+ if(c == "A") n = 16 * n + 10
+ if(c == "B") n = 16 * n + 11
+ if(c == "C") n = 16 * n + 12
+ if(c == "D") n = 16 * n + 13
+ if(c == "E") n = 16 * n + 14
+ if(c == "F") n = 16 * n + 15
+ } else {
+ error("bad hex digit '" c "'")
+ }
+ }
+ return n
+}
+
+function error(str)
+{
+ print "error:" str >"/dev/stderr"
+ exit 1
+}
diff --git a/sys/contrib/ngatm/netnatm/msg/priv.h b/sys/contrib/ngatm/netnatm/msg/priv.h
new file mode 100644
index 000000000000..aa13fc467d46
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/priv.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/msg/priv.h,v 1.4 2003/10/10 14:50:05 hbb Exp $
+ *
+ * Private definitions for the IE code file.
+ */
+#ifndef unimsg_priv_h
+#define unimsg_priv_h
+
+#ifdef _KERNEL
+#include <sys/systm.h>
+#include <machine/stdarg.h>
+#define PANIC(X) panic X
+#else
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#define PANIC(X) abort()
+#endif
+
+/*
+ * Define a structure for the declaration of information elements.
+ * For each coding scheme a quadrupel of check, print, encode and
+ * decode functions must be defined. A structure of the same format
+ * is used for messages.
+ */
+typedef void (*uni_print_f)(const union uni_ieall *, struct unicx *);
+typedef int (*uni_check_f)(union uni_ieall *, struct unicx *);
+typedef int (*uni_encode_f)(struct uni_msg *, union uni_ieall *,
+ struct unicx *);
+typedef int (*uni_decode_f)(union uni_ieall *, struct uni_msg *, u_int,
+ struct unicx *);
+
+typedef void (*uni_msg_print_f)(const union uni_msgall *, struct unicx *);
+typedef int (*uni_msg_check_f)(struct uni_all *, struct unicx *);
+typedef int (*uni_msg_encode_f)(struct uni_msg *, union uni_msgall *,
+ struct unicx *);
+typedef int (*uni_msg_decode_f)(union uni_msgall *, struct uni_msg *,
+ enum uni_ietype, struct uni_iehdr *, u_int, struct unicx *);
+
+struct iedecl {
+ u_int flags; /* information element flags */
+ u_int maxlen; /* maximum size */
+ uni_print_f print;
+ uni_check_f check;
+ uni_encode_f encode;
+ uni_decode_f decode;
+};
+
+struct msgdecl {
+ u_int flags;
+ const char *name;
+ uni_msg_print_f print;
+ uni_msg_check_f check;
+ uni_msg_encode_f encode;
+ uni_msg_decode_f decode;
+};
+
+enum {
+ UNIFL_DEFAULT = 0x0001,
+ UNIFL_ACCESS = 0x0002,
+};
+
+extern const struct iedecl *uni_ietable[256][4];
+extern const struct msgdecl *uni_msgtable[256];
+
+/*
+ * Need to check range here because declaring a variable as a enum does not
+ * guarantee that the values will be legal.
+ */
+#define GET_IEDECL(IE, CODING) \
+({ \
+ const struct iedecl *_decl = NULL; \
+ \
+ if((CODING) <= 3 && (IE) <= 255) \
+ if((_decl = uni_ietable[IE][CODING]) != NULL) \
+ if((_decl->flags & UNIFL_DEFAULT) != 0) \
+ if((_decl = uni_ietable[IE][0]) == NULL) \
+ PANIC(("IE %02x,%02x -- no default", CODING,IE));\
+ _decl; \
+})
+
+
+enum {
+ DEC_OK,
+ DEC_ILL,
+ DEC_ERR,
+};
+
+void uni_print_ie_internal(enum uni_ietype, const union uni_ieall *,
+ struct unicx *);
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/msg/privmsg.c b/sys/contrib/ngatm/netnatm/msg/privmsg.c
new file mode 100644
index 000000000000..76a7f69aa3c6
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/privmsg.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/msg/privmsg.c,v 1.8 2003/10/10 14:50:05 hbb Exp $
+ *
+ * Private definitions for the MSG code file.
+ *
+ * This file is included at the begin of the automatically generated
+ * uni_msg.c.
+ */
+
+/*
+ * Decode a UNI message header.
+ * Return values:
+ * 0 - ok
+ * -1 - ignore message (proto, length, CR error)
+ */
+int
+uni_decode_head(struct uni_msg *msg, struct uni_all *out,
+ struct unicx *cx __unused)
+{
+ u_int mlen;
+
+ cx->errcnt = 0;
+ (void)memset(out, 0, sizeof(struct uni_all));
+
+ if(uni_msg_len(msg) < 9)
+ return -1; /* Q.2931 5.6.2 */
+ if(cx->pnni) {
+ if(*msg->b_rptr++ != PNNI_PROTO)
+ return -1; /* Q.2931 5.6.1 */
+ } else {
+ if(*msg->b_rptr++ != UNI_PROTO)
+ return -1; /* Q.2931 5.6.1 */
+ }
+ if(*msg->b_rptr++ != 3)
+ return -1; /* Q.2931 5.6.3.1 */
+
+ out->u.hdr.cref.flag = (*msg->b_rptr & 0x80) ? 1 : 0;
+ out->u.hdr.cref.cref = (*msg->b_rptr++ & 0x7f) << 16;
+ out->u.hdr.cref.cref |= *msg->b_rptr++ << 8;
+ out->u.hdr.cref.cref |= *msg->b_rptr++;
+
+ out->mtype = *msg->b_rptr++;
+
+ /*
+ * Be not too piggy about this byte
+ */
+ switch(*msg->b_rptr & 0x13) {
+
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ out->u.hdr.act = UNI_MSGACT_DEFAULT;
+ break;
+
+ case 0x10: case 0x11: case 0x12:
+ out->u.hdr.act = *msg->b_rptr & 0x3;
+ break;
+
+ case 0x13: /* Q.2931 5.7.1 */
+ out->u.hdr.act = UNI_MSGACT_REPORT;
+ break;
+ }
+ if(cx->pnni && (*msg->b_rptr & 0x08))
+ out->u.hdr.pass = 1;
+ else
+ out->u.hdr.pass = 0;
+
+ msg->b_rptr++;
+
+ mlen = *msg->b_rptr++ << 8;
+ mlen |= *msg->b_rptr++;
+
+ /*
+ * If the message is longer than the indicated length
+ * shorten it. If it is shorter, probably one of the IE
+ * decoders will break, but we should proceed. 5.5.6.5
+ */
+#if 0
+ if(uni_msg_len(msg) > mlen)
+ msg->b_wptr = msg->b_rptr + mlen;
+#endif
+
+ return 0;
+}
+
+static int
+uni_decode_body_internal(enum uni_msgtype mtype, struct uni_msg *msg,
+ union uni_msgall *out, struct unicx *cx)
+{
+ enum uni_ietype ietype;
+ struct uni_iehdr hdr;
+ u_int ielen;
+ const struct iedecl *iedecl;
+ int err = 0, ret;
+ u_char *end;
+
+ cx->ielast = (enum uni_ietype)0;
+ cx->repeat.h.present = 0;
+
+ while (uni_msg_len(msg) != 0) {
+ if (uni_decode_ie_hdr(&ietype, &hdr, msg, cx, &ielen)) {
+ /*
+ * Short header. Set the ielen to an impossible size.
+ * Then we should bump out in the error handling below.
+ * We should have at least an IE type here.
+ */
+ ielen = 0xffffffff;
+ }
+#ifdef DTRACE
+ printf("IE %x\n", ietype);
+#endif
+
+ if ((iedecl = GET_IEDECL(ietype, hdr.coding)) == NULL ||
+ ietype == UNI_IE_UNREC) {
+ /*
+ * entirly unknown IE. Check the length and skip it.
+ * Q.2931 5.6.8.1
+ */
+ if (ielen > uni_msg_len(msg))
+ msg->b_rptr = msg->b_wptr;
+ else
+ msg->b_rptr += ielen;
+ (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK);
+ err = -1;
+ continue;
+ }
+#ifdef DTRACE
+ printf("IE %x known\n", ietype);
+#endif
+ if (ielen > iedecl->maxlen - 4 || ielen > uni_msg_len(msg)) {
+ /*
+ * Information element too long -> content error.
+ * Let the decoding routine set the error flag and
+ * return DEC_ERR.
+ * Q.2931 5.6.8.2
+ */
+#if 0
+ /*
+ * It is not clear how to best handle this error.
+ */
+ if (ielen > iedecl->maxlen - 4)
+ ielen = iedecl->maxlen - 4;
+#endif
+
+ if (ielen > uni_msg_len(msg))
+ ielen = uni_msg_len(msg);
+
+ hdr.present |= UNI_IE_ERROR;
+
+#ifdef DTRACE
+ printf("IE %x length too large\n", ietype);
+#endif
+ }
+
+#ifdef DTRACE
+ else
+ printf("IE %x length ok\n", ietype);
+#endif
+ end = msg->b_rptr + ielen;
+ ret = uni_msgtable[mtype]->decode(out, msg, ietype,
+ &hdr, ielen, cx);
+ msg->b_rptr = end;
+
+#ifdef DTRACE
+ printf("IE %x ret %d\n", ietype, ret);
+#endif
+
+ switch (ret) {
+
+ case DEC_OK: /* ok */
+ break;
+
+ case DEC_ILL: /* illegal IE */
+ /*
+ * Unexpected but recognized.
+ * Q.2931 5.6.8.3
+ */
+ (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK);
+ err = -1;
+ break;
+
+ case DEC_ERR: /* bad IE */
+ if (iedecl->flags & UNIFL_ACCESS)
+ /* this may be wrong: 5.6.8.2 */
+ (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_ACC);
+ else
+ (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_BAD);
+ err = -1;
+ break;
+
+ default:
+ PANIC(("bad decode return"));
+ }
+ cx->ielast = ietype;
+ if (ietype != UNI_IE_REPEAT)
+ cx->repeat.h.present = 0;
+ }
+ return err;
+}
+
+/*
+ * Decode the body of a message. The header is assumed to be decoded
+ * already and out->hdr is filled in. Only information elements remain.
+ */
+int
+uni_decode_body(struct uni_msg *msg, struct uni_all *out, struct unicx *cx)
+{
+ cx->errcnt = 0;
+ if (out->mtype >= 256)
+ return (-1);
+ if (uni_msgtable[out->mtype] == NULL)
+ return (-1);
+ return (uni_decode_body_internal(out->mtype, msg, &out->u, cx));
+}
+
+
+/*
+ * Decode a uni message
+ */
+int
+uni_decode(struct uni_msg *msg, struct uni_all *out, struct unicx *cx)
+{
+ cx->errcnt = 0;
+ if (uni_decode_head(msg, out, cx))
+ return (-1);
+ if (uni_decode_body(msg, out, cx))
+ return (-2);
+ return (0);
+}
+
+int
+uni_encode(struct uni_msg *msg, struct uni_all *in, struct unicx *cx)
+{
+ if (in->mtype >= 256)
+ return (-1);
+ if (uni_msgtable[in->mtype] == NULL)
+ return (-3);
+
+ return ((uni_msgtable[in->mtype]->encode)(msg, &in->u, cx));
+}
+
+/*
+ * Doesn't belong here
+ */
+void
+uni_initcx(struct unicx *cx)
+{
+ memset(cx, 0, sizeof(struct unicx));
+ cx->tabsiz = 4;
+}
diff --git a/sys/contrib/ngatm/netnatm/msg/traffic.c b/sys/contrib/ngatm/netnatm/msg/traffic.c
new file mode 100644
index 000000000000..acaffdbbe7d4
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/traffic.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/msg/traffic.c,v 1.4 2004/07/08 08:22:05 brandt Exp $
+ *
+ * Traffic classification
+ */
+
+#include <netnatm/unimsg.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <stdio.h>
+#endif
+
+/*
+ * Try to set the parameters for the CPCS from the parameters of the
+ * connection.
+ */
+enum {
+ T_CBR23 = 100, T_nrtVBR2_6_UBR12, T_rtVBR236, T_rtVBR2_6
+};
+
+static const u_int fmask = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P |
+ UNI_TRAFFIC_FSCR0_P | UNI_TRAFFIC_FSCR1_P | UNI_TRAFFIC_FMBS0_P |
+ UNI_TRAFFIC_FMBS1_P | UNI_TRAFFIC_FABR1_P;
+static const u_int bmask = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P |
+ UNI_TRAFFIC_BSCR0_P | UNI_TRAFFIC_BSCR1_P | UNI_TRAFFIC_BMBS0_P |
+ UNI_TRAFFIC_BMBS1_P | UNI_TRAFFIC_BABR1_P;
+
+static const u_int fcbr3 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P;
+static const u_int bcbr3 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P;
+static const u_int fvbr16 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR1_P |
+ UNI_TRAFFIC_FMBS1_P;
+static const u_int bvbr16 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR1_P |
+ UNI_TRAFFIC_BMBS1_P;
+static const u_int fvbr23 = UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_FSCR0_P |
+ UNI_TRAFFIC_FMBS0_P;
+static const u_int bvbr23 = UNI_TRAFFIC_BPCR1_P | UNI_TRAFFIC_BSCR0_P |
+ UNI_TRAFFIC_BMBS0_P;
+static const u_int fvbr4 = UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P;
+static const u_int bvbr4 = UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P;
+
+int
+uni_classify_traffic(const struct uni_ie_bearer *bearer,
+ const struct uni_ie_traffic *traffic,
+ enum uni_traffic_class *fclass, enum uni_traffic_class *bclass,
+ char *ebuf, size_t ebufsiz)
+{
+ u_int tclass;
+ u_int ft, bt, be, ftag, btag;
+
+ /* classify */
+ switch (bearer->bclass) {
+
+ case UNI_BEARER_A:
+ if (!(bearer->h.present & UNI_BEARER_ATC_P)) {
+ tclass = T_CBR23;
+ break;
+ }
+ switch (bearer->atc) {
+
+ case UNI_BEARER_ATC_CBR1:
+ tclass = UNI_TRAFFIC_CBR1;
+ break;
+
+ default:
+ snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-A",
+ bearer->atc);
+ return (-1);
+ }
+ break;
+
+ case UNI_BEARER_C:
+ if (!(bearer->h.present & UNI_BEARER_ATC_P)) {
+ tclass = T_nrtVBR2_6_UBR12;
+ break;
+ }
+ switch (bearer->atc) {
+
+ case UNI_BEARER_ATC_VBR1:
+ tclass = UNI_TRAFFIC_rtVBR1;
+ break;
+
+ case UNI_BEARER_ATC_VBR:
+ tclass = T_rtVBR236;
+ break;
+
+ case UNI_BEARER_ATC_NVBR1:
+ tclass = UNI_TRAFFIC_nrtVBR1;
+ break;
+
+ case UNI_BEARER_ATC_ABR:
+ tclass = UNI_TRAFFIC_ABR;
+ break;
+
+ default:
+ snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-C",
+ bearer->atc);
+ return (-1);
+ }
+ break;
+
+ case UNI_BEARER_X:
+ if (!(bearer->h.present & UNI_BEARER_ATC_P)) {
+ tclass = T_nrtVBR2_6_UBR12;
+ break;
+ }
+ switch (bearer->atc) {
+
+ case UNI_BEARER_ATC_CBR1:
+ tclass = UNI_TRAFFIC_CBR1;
+ break;
+
+ case UNI_BEARER_ATC_CBR:
+ case UNI_BEARER_ATCX_4:
+ case UNI_BEARER_ATCX_6:
+ tclass = T_CBR23;
+ break;
+
+ case UNI_BEARER_ATC_VBR1:
+ tclass = UNI_TRAFFIC_rtVBR1;
+ break;
+
+ case UNI_BEARER_ATCX_1:
+ case UNI_BEARER_ATC_VBR:
+ tclass = T_rtVBR2_6;
+ break;
+
+ case UNI_BEARER_ATC_NVBR1:
+ tclass = UNI_TRAFFIC_nrtVBR1;
+ break;
+
+ case UNI_BEARER_ATCX_0:
+ case UNI_BEARER_ATCX_2:
+ case UNI_BEARER_ATCX_8:
+ case UNI_BEARER_ATC_NVBR:
+ tclass = T_nrtVBR2_6_UBR12;
+ break;
+
+ case UNI_BEARER_ATC_ABR:
+ tclass = UNI_TRAFFIC_ABR;
+ break;
+
+ default:
+ snprintf(ebuf, ebufsiz, "bad ATC=%#02x for BCOB-X",
+ bearer->atc);
+ return (-1);
+ }
+ break;
+
+ case UNI_BEARER_TVP:
+ snprintf(ebuf, ebufsiz, "unsupported bearer class tVP");
+ return (-1);
+
+ default:
+ snprintf(ebuf, ebufsiz, "bad bearer class %#02x",
+ bearer->bclass);
+ return (-1);
+ }
+
+ /*
+ * Now traffic IE
+ */
+ ft = traffic->h.present & fmask;
+ bt = traffic->h.present & bmask;
+ be = traffic->h.present & UNI_TRAFFIC_BEST_P;
+ ftag = (traffic->h.present & UNI_TRAFFIC_MOPT_P) && traffic->t.ftag;
+ btag = (traffic->h.present & UNI_TRAFFIC_MOPT_P) && traffic->t.btag;
+
+#define NOBE(C) \
+ if (be) { \
+ snprintf(ebuf, ebufsiz, "illegal BE for " C); \
+ return (-1); \
+ }
+
+#define NOFT(C) \
+ if (ftag) { \
+ snprintf(ebuf, ebufsiz, "illegal forward tag in " C); \
+ return (-1); \
+ }
+
+#define NOBT(C) \
+ if (btag) { \
+ snprintf(ebuf, ebufsiz, "illegal backward tag in " C); \
+ return (-1); \
+ }
+
+#define FBAD(C) do { \
+ snprintf(ebuf, ebufsiz, "bad forward CRs for " C); \
+ return (-1); \
+ } while (0)
+
+#define BBAD(C) do { \
+ snprintf(ebuf, ebufsiz, "bad backward CRs for " C); \
+ return (-1); \
+ } while (0)
+
+ switch (tclass) {
+
+ case UNI_TRAFFIC_CBR1:
+ NOBE("CBR.1");
+ if (ft != UNI_TRAFFIC_FPCR1_P)
+ FBAD("CBR.1");
+ NOFT("CBR.1");
+ if (bt != UNI_TRAFFIC_BPCR1_P)
+ BBAD("CBR.1");
+ NOBT("CBR.1");
+ *fclass = *bclass = UNI_TRAFFIC_CBR1;
+ break;
+
+ case T_CBR23:
+ NOBE("CBR.2/3");
+ if (ft == UNI_TRAFFIC_FPCR0_P) {
+ *fclass = UNI_TRAFFIC_CBR2;
+ NOFT("CBR.2");
+ } else if (ft == fcbr3) {
+ *fclass = UNI_TRAFFIC_CBR3;
+ if (!ftag) {
+ snprintf(ebuf, ebufsiz, "need forward tagging for CBR.3");
+ return (-1);
+ }
+ } else
+ FBAD("CBR.2/3");
+ if (bt == UNI_TRAFFIC_BPCR0_P) {
+ *bclass = UNI_TRAFFIC_CBR2;
+ NOBT("CBR.2");
+ } else if (bt == bcbr3) {
+ *bclass = UNI_TRAFFIC_CBR3;
+ if (!btag) {
+ snprintf(ebuf, ebufsiz, "need backward tagging for CBR.3");
+ return (-1);
+ }
+ } else
+ BBAD("CBR.2/3");
+ break;
+
+ case UNI_TRAFFIC_rtVBR1:
+ NOBE("rtVBR.1");
+ if (ft != fvbr16)
+ FBAD("rtVBR.1");
+ NOFT("rtVBR.1");
+ if (bt != bvbr16)
+ BBAD("rtVBR.1");
+ NOBT("rtVBR.1");
+ *fclass = *bclass = UNI_TRAFFIC_rtVBR1;
+ break;
+
+ case T_rtVBR236:
+ NOBE("rtVBR.2/3/6");
+ if (ft == fvbr23) {
+ if (ftag)
+ *fclass = UNI_TRAFFIC_rtVBR3;
+ else
+ *fclass = UNI_TRAFFIC_rtVBR2;
+ } else if (ft == fvbr16) {
+ *fclass = UNI_TRAFFIC_rtVBR6;
+ NOFT("rtVBR.6");
+ } else
+ FBAD("rtVBR.2/3/6");
+ if (bt == bvbr23) {
+ if (btag)
+ *bclass = UNI_TRAFFIC_rtVBR3;
+ else
+ *bclass = UNI_TRAFFIC_rtVBR2;
+ } else if (bt == bvbr16) {
+ *bclass = UNI_TRAFFIC_rtVBR6;
+ NOBT("rtVBR.6");
+ } else
+ BBAD("rtVBR.2/3/6");
+ break;
+
+ case T_rtVBR2_6:
+ NOBE("rtVBR.2-6");
+ if (ft == fvbr23) {
+ if (ftag)
+ *fclass = UNI_TRAFFIC_rtVBR3;
+ else
+ *fclass = UNI_TRAFFIC_rtVBR2;
+ } else if (ft == fvbr4) {
+ *fclass = UNI_TRAFFIC_rtVBR4;
+ } else if (ft == UNI_TRAFFIC_FPCR1_P) {
+ *fclass = UNI_TRAFFIC_rtVBR5;
+ NOFT("rtVBR.5");
+ } else if (ft == fvbr16) {
+ *fclass = UNI_TRAFFIC_rtVBR6;
+ NOFT("rtVBR.6");
+ } else
+ FBAD("rtVBR.2-6");
+ if (bt == bvbr23) {
+ if (btag)
+ *bclass = UNI_TRAFFIC_rtVBR3;
+ else
+ *bclass = UNI_TRAFFIC_rtVBR2;
+ } else if (bt == bvbr4) {
+ *bclass = UNI_TRAFFIC_rtVBR4;
+ } else if (bt == UNI_TRAFFIC_BPCR1_P) {
+ *bclass = UNI_TRAFFIC_rtVBR5;
+ NOBT("rtVBR.5");
+ } else if (bt == bvbr16) {
+ *bclass = UNI_TRAFFIC_rtVBR6;
+ NOBT("rtVBR.6");
+ } else
+ BBAD("rtVBR.2-6");
+ break;
+
+ case UNI_TRAFFIC_nrtVBR1:
+ NOBE("nrtVBR.1");
+ if (ft != fvbr16)
+ FBAD("nrtVBR.1");
+ NOFT("nrtVBR.1");
+ if (bt != bvbr16)
+ BBAD("nrtVBR.1");
+ NOBT("nrtVBR.1");
+ *fclass = *bclass = UNI_TRAFFIC_nrtVBR1;
+ break;
+
+ case T_nrtVBR2_6_UBR12:
+ if (be) {
+ if (ft != UNI_TRAFFIC_FPCR1_P)
+ FBAD("UBR.1/2");
+ if (bt != UNI_TRAFFIC_BPCR1_P)
+ BBAD("UBR.1/2");
+ if (ftag)
+ *fclass = UNI_TRAFFIC_UBR2;
+ else
+ *fclass = UNI_TRAFFIC_UBR1;
+ if (btag)
+ *bclass = UNI_TRAFFIC_UBR2;
+ else
+ *bclass = UNI_TRAFFIC_UBR1;
+ break;
+ }
+ if (ft == fvbr23) {
+ if (ftag)
+ *fclass = UNI_TRAFFIC_nrtVBR3;
+ else
+ *fclass = UNI_TRAFFIC_nrtVBR2;
+ } else if (ft == fvbr4) {
+ *fclass = UNI_TRAFFIC_nrtVBR4;
+ } else if (ft == UNI_TRAFFIC_FPCR1_P) {
+ *fclass = UNI_TRAFFIC_nrtVBR5;
+ NOFT("nrtVBR.5");
+ } else if (ft == fvbr16) {
+ *fclass = UNI_TRAFFIC_nrtVBR6;
+ NOFT("nrtVBR.6");
+ } else
+ FBAD("nrtVBR.2-6");
+ if (bt == bvbr23) {
+ if (btag)
+ *bclass = UNI_TRAFFIC_nrtVBR3;
+ else
+ *bclass = UNI_TRAFFIC_nrtVBR2;
+ } else if (bt == bvbr4) {
+ *bclass = UNI_TRAFFIC_nrtVBR4;
+ } else if (bt == UNI_TRAFFIC_BPCR1_P) {
+ *bclass = UNI_TRAFFIC_nrtVBR5;
+ NOBT("nrtVBR.5");
+ } else if (bt == bvbr16) {
+ *bclass = UNI_TRAFFIC_nrtVBR6;
+ NOBT("nrtVBR.6");
+ } else
+ BBAD("nrtVBR.2-6");
+ break;
+
+ case UNI_TRAFFIC_ABR:
+ NOBE("ABR");
+ if (ft != UNI_TRAFFIC_FPCR1_P)
+ FBAD("ABR");
+ if (bt != UNI_TRAFFIC_BPCR1_P)
+ BBAD("ABR");
+ NOFT("ABR");
+ NOBT("ABR");
+ *fclass = *bclass = UNI_TRAFFIC_ABR;
+ break;
+ }
+
+ return (0);
+}
diff --git a/sys/contrib/ngatm/netnatm/msg/uni_config.h b/sys/contrib/ngatm/netnatm/msg/uni_config.h
new file mode 100644
index 000000000000..e53f59b8395c
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uni_config.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $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_
+
+enum {
+ /* maximum number of reported error IEs */
+ UNI_MAX_ERRIE = 50,
+
+ /* maximum number of Generic Identifier Transport IE's per message */
+ UNI_NUM_IE_GIT = 3,
+
+ /* maximum number of BLLI's in SETUP */
+ UNI_NUM_IE_BLLI = 3,
+
+ /* maximum number of CALLEDSUB's */
+ UNI_NUM_IE_CALLEDSUB = 2,
+
+ /* maximum number of CALLINGSUB's */
+ UNI_NUM_IE_CALLINGSUB = 2,
+
+ /* maximum number of TNS's */
+ UNI_NUM_IE_TNS = 4,
+
+ /* maximum length of TNS name */
+ UNI_TNS_MAXLEN = 4,
+
+ /* maximum info size in user-to-user signalling IE */
+ UNI_UU_MAXLEN = 128,
+
+ /* maximum length of address */
+ UNI_ADDR_MAXLEN = 20,
+
+ /* maximum length of subaddress */
+ UNI_SUBADDR_MAXLEN = 20,
+
+ /* maximum number of DTLs */
+ UNI_NUM_IE_DTL = 10,
+ /* maximum number of identifiers in DTL */
+ UNI_DTL_MAXNUM = 20,
+};
+#endif
diff --git a/sys/contrib/ngatm/netnatm/msg/uni_hdr.h b/sys/contrib/ngatm/netnatm/msg/uni_hdr.h
new file mode 100644
index 000000000000..c9a30f12be5d
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uni_hdr.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $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>
+
+enum {
+ UNI_PROTO = 0x09, /* protocol discriminator */
+ PNNI_PROTO = 0xf0, /* PNNI protocol discriminator */
+};
+
+/*
+ * Message types
+ */
+enum uni_msgtype {
+ UNI_UNKNOWN = 0x100,/* unknown message */
+
+ UNI_ALERTING = 0x01, /* alerting */
+ UNI_CALL_PROC = 0x02, /* call proceeding */
+ UNI_SETUP = 0x05, /* setup */
+ UNI_CONNECT = 0x07, /* connect */
+ UNI_CONNECT_ACK = 0x0f, /* connect ack */
+
+ UNI_RESTART = 0x46, /* restart */
+ UNI_RELEASE = 0x4d, /* release */
+ UNI_RESTART_ACK = 0x4e, /* restart acknowledgement */
+ UNI_RELEASE_COMPL = 0x5a, /* release complete */
+
+ UNI_NOTIFY = 0x6e, /* notify user */
+ UNI_STATUS_ENQ = 0x75, /* status enquiry */
+ UNI_STATUS = 0x7d, /* status */
+
+ UNI_ADD_PARTY = 0x80, /* add party */
+ UNI_ADD_PARTY_ACK = 0x81, /* add party acknowledgement */
+ UNI_ADD_PARTY_REJ = 0x82, /* add party reject */
+ UNI_DROP_PARTY = 0x83, /* drop party */
+ UNI_DROP_PARTY_ACK = 0x84, /* drop party acknowledgement */
+ UNI_PARTY_ALERTING = 0x85, /* party alerting */
+
+ UNI_LEAF_SETUP_FAIL = 0x90, /* leaf setup failed */
+ UNI_LEAF_SETUP_REQ = 0x91, /* leaf setup request */
+
+ UNI_COBISETUP = 0x15, /* Q.2932 COBI-setup */
+ UNI_FACILITY = 0x62, /* Q.2932 facility */
+
+ UNI_MODIFY_REQ = 0x88, /* Q.2963 Modify request */
+ UNI_MODIFY_ACK = 0x89, /* Q.2963 Modify acknowledgement */
+ UNI_MODIFY_REJ = 0x8a, /* Q.2963 Modify reject */
+ UNI_CONN_AVAIL = 0x8b, /* Q.2963 Connection available */
+};
+
+/*
+ * Information element types
+ */
+enum uni_ietype {
+ UNI_IE_CAUSE = 0x08, /* cause */
+ UNI_IE_CALLSTATE = 0x14, /* call state */
+ UNI_IE_FACILITY = 0x1C, /* Q.2932 facility IE */
+ UNI_IE_NOTIFY = 0x27, /* UNI4.0 notify */
+ UNI_IE_EETD = 0x42, /* UNI4.0 end-to-end transit delay */
+ UNI_IE_CONNED = 0x4c, /* UNI4.0/Q.2951 connected address */
+ UNI_IE_CONNEDSUB = 0x4d, /* UNI4.0/Q.2951 connected subaddress */
+ UNI_IE_EPREF = 0x54, /* endpoint reference */
+ UNI_IE_EPSTATE = 0x55, /* enpoint state */
+ UNI_IE_AAL = 0x58, /* ATM adaptation layer parameters */
+ UNI_IE_TRAFFIC = 0x59, /* ATM traffic descriptor */
+ UNI_IE_CONNID = 0x5a, /* connection identifier */
+ UNI_IE_QOS = 0x5c, /* quality of service parameter */
+ UNI_IE_BHLI = 0x5d, /* broadband higher layer information */
+ UNI_IE_BEARER = 0x5e, /* broadband bearer capability */
+ UNI_IE_BLLI = 0x5f, /* broadband lower layer information */
+ UNI_IE_LSHIFT = 0x60, /* broadband locking shift */
+ UNI_IE_NLSHIFT = 0x61, /* broadband non-locking shift */
+ UNI_IE_SCOMPL = 0x62, /* broadband sending complete */
+ UNI_IE_REPEAT = 0x63, /* broadband repeat indicator */
+ UNI_IE_CALLING = 0x6c, /* calling party number */
+ UNI_IE_CALLINGSUB = 0x6d, /* calling party subaddress */
+ UNI_IE_CALLED = 0x70, /* called party number */
+ UNI_IE_CALLEDSUB = 0x71, /* called party subaddress */
+ UNI_IE_TNS = 0x78, /* transit network selection */
+ UNI_IE_RESTART = 0x79, /* restart indicator */
+ UNI_IE_UU = 0x7e, /* UNI4.0/Q.2957 user-to-user info */
+ UNI_IE_GIT = 0x7f, /* UNI4.0 generic identifier transport*/
+ UNI_IE_MINTRAFFIC = 0x81, /* Q.2962 minimum traffic desc */
+ UNI_IE_ATRAFFIC = 0x82, /* Q.2962 alternate traffic desc */
+ UNI_IE_ABRSETUP = 0x84, /* UNI4.0 ABR setup parameters */
+ UNI_IE_REPORT = 0x89, /* Q.2963 broadband report type */
+ UNI_IE_CALLED_SOFT = 0xe0, /* PNNI Calling party soft PVPC */
+ UNI_IE_CRANKBACK = 0xe1, /* PNNI Crankback */
+ UNI_IE_DTL = 0xe2, /* PNNI designated transit list */
+ UNI_IE_CALLING_SOFT = 0xe3, /* PNNI Called party soft PVPC */
+ UNI_IE_ABRADD = 0xe4, /* UNI4.0 ABR additional parameters */
+ UNI_IE_LIJ_CALLID = 0xe8, /* UNI4.0 LIF call identifier */
+ UNI_IE_LIJ_PARAM = 0xe9, /* UNI4.0 LIF parameters */
+ UNI_IE_LIJ_SEQNO = 0xea, /* UNI4.0 LIF sequence number */
+ UNI_IE_CSCOPE = 0xeb, /* UNI4.0 connection scope selection */
+ UNI_IE_EXQOS = 0xec, /* UNI4.0 extended QoS parameters */
+ UNI_IE_MDCR = 0xf0, /* UNI4.0+ Minimum desired call rate */
+ UNI_IE_UNREC = 0xfe,
+};
+
+enum uni_coding {
+ UNI_CODING_ITU = 0x0,
+ UNI_CODING_NET = 0x3,
+};
+
+enum uni_msgact {
+ UNI_MSGACT_CLEAR = 0x0,
+ UNI_MSGACT_IGNORE = 0x1,
+ UNI_MSGACT_REPORT = 0x2,
+
+ UNI_MSGACT_DEFAULT = 0x4
+};
+
+enum uni_ieact {
+ UNI_IEACT_CLEAR = 0x00, /* clear call */
+ UNI_IEACT_IGNORE = 0x01, /* ignore IE and proceed */
+ UNI_IEACT_REPORT = 0x02, /* ignore IE, report and proceed */
+ UNI_IEACT_MSG_IGNORE = 0x05, /* ignore message */
+ UNI_IEACT_MSG_REPORT = 0x06, /* ignore message and report */
+
+ UNI_IEACT_DEFAULT = 0x08
+};
+
+struct uni_cref {
+ u_int flag;
+ u_int cref;
+};
+
+/*
+ * Message header.
+ */
+struct uni_msghdr {
+ struct uni_cref cref;
+ enum uni_msgact act; /* action indicator */
+ u_int pass:1; /* PNNI pass along request */
+};
+
+enum {
+ CREF_GLOBAL = 0,
+ CREF_DUMMY = 0x7fffff,
+};
+
+/*
+ * General information element header.
+ */
+struct uni_iehdr {
+ enum uni_coding coding; /* coding standard */
+ enum uni_ieact act; /* action indicator */
+ u_int pass : 1; /* PNNI pass along request */
+ u_int present; /* which optional elements are present */
+#define UNI_IE_EMPTY 0x80000000
+#define UNI_IE_PRESENT 0x40000000
+#define UNI_IE_ERROR 0x20000000
+#define UNI_IE_XXX 0x10000000
+#define UNI_IE_MASK 0xf0000000
+};
+
+#define IE_ISPRESENT(IE) \
+ (((IE).h.present & (UNI_IE_PRESENT|UNI_IE_EMPTY)) == UNI_IE_PRESENT)
+#define IE_SETPRESENT(IE) \
+ ((IE).h.present = ((IE).h.present & ~UNI_IE_MASK) | \
+ UNI_IE_PRESENT)
+
+#define IE_ADDPRESENT(IE) \
+ ((IE).h.present = ((IE).h.present & ~UNI_IE_EMPTY) | \
+ UNI_IE_PRESENT)
+
+#define IE_ISEMPTY(IE) \
+ (((IE).h.present & UNI_IE_MASK) == (UNI_IE_PRESENT | UNI_IE_EMPTY))
+#define IE_SETEMPTY(IE) \
+ ((IE).h.present = ((IE).h.present & ~UNI_IE_MASK) | \
+ UNI_IE_EMPTY | UNI_IE_PRESENT)
+
+#define IE_ISERROR(IE) \
+ (((IE).h.present & UNI_IE_MASK) == (UNI_IE_PRESENT | UNI_IE_ERROR))
+#define IE_SETERROR(IE) \
+ ((IE).h.present = ((IE).h.present & ~UNI_IE_MASK) | \
+ UNI_IE_ERROR | UNI_IE_PRESENT)
+
+#define IE_ISGOOD(IE) \
+ (((IE).h.present & UNI_IE_MASK) == (UNI_IE_PRESENT))
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/msg/uni_ie.c b/sys/contrib/ngatm/netnatm/msg/uni_ie.c
new file mode 100644
index 000000000000..e4b8310d88d9
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uni_ie.c
@@ -0,0 +1,7166 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/msg/uni_ie.c,v 1.16 2005/05/23 12:06:30 brandt_h Exp $
+ *
+ * Private definitions for the IE code file.
+ *
+ * This file includes the table generated automatically.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef _KERNEL
+#include <sys/libkern.h>
+#else
+#include <string.h>
+#endif
+#include <netnatm/unimsg.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/msg/uniprint.h>
+#include <netnatm/msg/priv.h>
+
+#define UNUSED(_p) do { (void)(_p); } while (0)
+
+/*
+ * Define internal functions.
+ */
+#define DEF_IE_PRINT(Coding, IE) \
+ void uni_ie_print_##Coding##_##IE(struct uni_ie_##IE *ie, struct unicx *cx)
+
+#define DEF_IE_CHECK(Coding, IE) \
+ int uni_ie_check_##Coding##_##IE(struct uni_ie_##IE *ie, struct unicx *cx)
+
+#define DEF_IE_ENCODE(Coding, IE) \
+ int uni_ie_encode_##Coding##_##IE(struct uni_msg *msg, struct uni_ie_##IE *ie, struct unicx *cx)
+
+#define DEF_IE_DECODE(Coding, IE) \
+ int uni_ie_decode_##Coding##_##IE(struct uni_ie_##IE *ie, struct uni_msg *msg, u_int ielen, struct unicx *cx)
+
+/*
+ * This structure is used to define value->string mappings. MKT() is used
+ * to generate a table entry. EOT() to end the table.
+ */
+#define MKT(V,N) { #N, V }
+#define EOT() { NULL, 0 }
+
+/* library internal functions */
+static void uni_entry(const char *, struct unicx *);
+static int uni_print_iehdr(const char *, struct uni_iehdr *h, struct unicx *);
+static void uni_print_ieend(struct unicx *);
+static void uni_putc(int, struct unicx *);
+
+
+/*
+ * Encoding
+ */
+#define APP_BYTE(M, B) do { \
+ *(M)->b_wptr++ = (B); \
+ } while (0)
+#define APP_16BIT(M, B) do { \
+ u_int _v = (B); \
+ *(M)->b_wptr++ = _v >> 8; \
+ *(M)->b_wptr++ = _v; \
+ } while (0)
+#define APP_24BIT(M, B) do { \
+ u_int _v = (B); \
+ *(M)->b_wptr++ = _v >> 16; \
+ *(M)->b_wptr++ = _v >> 8; \
+ *(M)->b_wptr++ = _v; \
+ } while (0)
+#define APP_32BIT(M, B) do { \
+ u_int _v = (B); \
+ *(M)->b_wptr++ = _v >> 24; \
+ *(M)->b_wptr++ = _v >> 16; \
+ *(M)->b_wptr++ = _v >> 8; \
+ *(M)->b_wptr++ = _v; \
+ } while (0)
+#define APP_BUF(M, B, L) do { \
+ (void)memcpy((M)->b_wptr, (B), (L)); \
+ (M)->b_wptr += (L); \
+ } while (0)
+
+#define APP_SUB_BYTE(M, T, B) do { APP_BYTE(M, T); APP_BYTE(M, B); } while (0)
+#define APP_SUB_16BIT(M, T, B) do { APP_BYTE(M, T); APP_16BIT(M, B); } while (0)
+#define APP_SUB_24BIT(M, T, B) do { APP_BYTE(M, T); APP_24BIT(M, B); } while (0)
+#define APP_SUB_32BIT(M, T, B) do { APP_BYTE(M, T); APP_32BIT(M, B); } while (0)
+
+#define APP_OPT(M, F, P, T) do { \
+ if ((F) & (P)) \
+ APP_BYTE((M), (T)); \
+ } while (0)
+#define APP_OPT_BYTE(M, F, P, T, B) do { \
+ if ((F) & (P)) \
+ APP_SUB_BYTE((M), (T), (B)); \
+ } while (0)
+#define APP_OPT_16BIT(M, F, P, T, B) do { \
+ if ((F) & (P)) \
+ APP_SUB_16BIT((M), (T), (B)); \
+ } while (0)
+#define APP_OPT_24BIT(M, F, P, T, B) do { \
+ if ((F) & (P)) \
+ APP_SUB_24BIT((M), (T), (B)); \
+ } while (0)
+
+#define START_IE(TYPE,CODE,LEN) \
+ u_int ielen; \
+ \
+ if (uni_check_ie(CODE, (union uni_ieall *)ie, cx)) \
+ return (-1); \
+ if (uni_encode_ie_hdr(msg, CODE, &ie->h, (LEN), cx)) \
+ return (0); \
+ \
+ ielen = msg->b_wptr - msg->b_rptr - 2;
+
+#define START_IE2(TYPE,CODE,LEN,REALCODE) \
+ u_int ielen; \
+ \
+ if (uni_check_ie(CODE, (union uni_ieall *)ie, cx)) \
+ return (-1); \
+ if (uni_encode_ie_hdr(msg, REALCODE, &ie->h, (LEN), cx)) \
+ return (0); \
+ \
+ ielen = msg->b_wptr - msg->b_rptr - 2;
+
+#define SET_IE_LEN(M) do { \
+ (M)->b_buf[ielen + 0] = \
+ (((M)->b_wptr - (M)->b_rptr) - ielen - 2) >> 8; \
+ (M)->b_buf[ielen + 1] = \
+ (((M)->b_wptr - (M)->b_rptr) - ielen - 2) >> 0; \
+ } while (0)
+
+
+/***********************************************************************/
+/*
+ * Decoding
+ */
+#define IE_START(ERR) \
+ if (IE_ISPRESENT(*ie)) \
+ return (0); \
+ if (ielen == 0) { \
+ IE_SETEMPTY(*ie); \
+ return (0); \
+ }
+
+#define IE_END(IE) \
+ IE_SETPRESENT(*ie); \
+ if (uni_check_ie(UNI_IE_##IE, (union uni_ieall *)ie, cx) == 0) \
+ return (0); \
+ rej: \
+ ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT; \
+ return (1);
+
+#define DEC_GETF3(ID, F, P) \
+ case UNI_##ID##_ID: \
+ if (ielen < 3) \
+ goto rej; \
+ ielen -= 3; \
+ if (!(P & UNI_##ID##_P)) { \
+ P |= UNI_##ID##_P; \
+ ie->F = *msg->b_rptr++ << 16; \
+ ie->F |= *msg->b_rptr++ << 8; \
+ ie->F |= *msg->b_rptr++; \
+ } else \
+ msg->b_rptr += 3; \
+ break;
+
+#define DEC_GETF1(ID, F, P) \
+ case UNI_##ID##_ID: \
+ if (ielen < 1) \
+ goto rej; \
+ ielen--; \
+ if (!(P & UNI_##ID##_P)) { \
+ P |= UNI_##ID##_P; \
+ ie->F = *msg->b_rptr++; \
+ } else \
+ msg->b_rptr++; \
+ break;
+
+
+#define PRINT_NPREFIX (sizeof(((struct unicx *)0)->prefix) / \
+ sizeof(((struct unicx *)0)->prefix[0]))
+
+/*
+ * This is rather here than in privmsg.c because we need the APP macros.
+ */
+int
+uni_encode_msg_hdr(struct uni_msg *msg, struct uni_msghdr *h,
+ enum uni_msgtype type, struct unicx *cx, int *mlen)
+{
+ u_char byte;
+
+ (void)uni_msg_ensure(msg, 9);
+
+ APP_BYTE(msg, cx->pnni ? PNNI_PROTO : UNI_PROTO);
+ APP_BYTE(msg, 3);
+ if(h->cref.cref >= 1<<23)
+ return -1;
+ APP_24BIT(msg, h->cref.cref | (h->cref.flag ? 0x800000 : 0));
+ APP_BYTE(msg, type);
+
+ byte = 0x80;
+ if(h->act != UNI_MSGACT_DEFAULT)
+ byte |= 0x10 | (h->act & 3);
+ if(cx->pnni && h->pass)
+ byte |= 0x08;
+ APP_BYTE(msg, byte);
+
+ *mlen = msg->b_wptr - msg->b_rptr;
+ APP_16BIT(msg, 0);
+
+ return 0;
+}
+
+/*
+ * Initialize printing. This must be called by all printing routines
+ * that are exported to the user.
+ */
+void
+uni_print_init(char *buf, size_t bufsiz, struct unicx *cx)
+{
+ if (cx->dont_init)
+ return;
+
+ cx->indent = 0;
+ cx->nprefix = 0;
+ cx->doindent = 0;
+ if (cx->tabsiz == 0)
+ cx->tabsiz = 4;
+ cx->buf = buf;
+ cx->bufsiz = bufsiz;
+}
+
+/*
+ * Append a character to the buffer if there is still space
+ */
+static void
+uni_putc(int c, struct unicx *cx)
+{
+ if(cx->bufsiz > 1) {
+ *cx->buf++ = c;
+ cx->bufsiz--;
+ *cx->buf = '\0';
+ }
+}
+
+void
+uni_printf(struct unicx *cx, const char *fmt, ...)
+{
+ u_int n;
+ va_list ap;
+
+ if(cx->bufsiz > 1) {
+ va_start(ap, fmt);
+ n = vsnprintf(cx->buf, cx->bufsiz, fmt, ap);
+ va_end(ap);
+ if(n > 0) {
+ if(n < cx->bufsiz) {
+ cx->bufsiz -= n;
+ cx->buf += n;
+ } else {
+ cx->buf += cx->bufsiz - 1;
+ cx->bufsiz = 1;
+ }
+ }
+ *cx->buf = '\0';
+ }
+}
+
+/*
+ * Print mode:
+ * 0 - print all into one line, fully prefixed
+ * 1 - print on multiple lines, full prefixed, but equal level
+ * entries on one line
+ * 2 - like 2, but only partial prefixed
+ * 3 - like 1, but each entry onto a new line
+ * 4 - like 2 + 3
+ */
+
+/*
+ * If we are in multiline mode, end the current line and set the
+ * flag, that we need indentation. But prevent double new lines.
+ */
+void
+uni_print_eol(struct unicx *cx)
+{
+ if (cx->multiline) {
+ if (!cx->doindent) {
+ uni_putc('\n', cx);
+ cx->doindent = 1;
+ }
+ }
+}
+
+/*
+ * New entry. Do the prefixing, indentation and spacing.
+ */
+static void
+doprefix(struct unicx *cx, const char *s)
+{
+ u_int i;
+
+ if(cx->multiline == 0) {
+ uni_putc(' ', cx);
+ for(i = 0; i < cx->nprefix; i++)
+ if(cx->prefix[i])
+ uni_printf(cx, "%s.", cx->prefix[i]);
+ } else if(cx->multiline == 1) {
+ if(cx->doindent) {
+ uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
+ cx->doindent = 0;
+ } else
+ uni_putc(' ', cx);
+ for(i = 0; i < cx->nprefix; i++)
+ if(cx->prefix[i])
+ uni_printf(cx, "%s.", cx->prefix[i]);
+ } else if(cx->multiline == 2) {
+ if(cx->doindent) {
+ uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
+ cx->doindent = 0;
+ } else
+ uni_putc(' ', cx);
+ } else if(cx->multiline == 3) {
+ if(cx->doindent)
+ cx->doindent = 0;
+ else
+ uni_putc('\n', cx);
+ uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
+ for(i = 0; i < cx->nprefix; i++)
+ if(cx->prefix[i])
+ uni_printf(cx, "%s.", cx->prefix[i]);
+ } else if(cx->multiline == 4) {
+ if(cx->doindent)
+ cx->doindent = 0;
+ else
+ uni_putc('\n', cx);
+ uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
+ }
+ uni_printf(cx, "%s", s);
+}
+static void
+uni_entry(const char *s, struct unicx *cx)
+{
+ doprefix(cx, s);
+ uni_putc('=', cx);
+}
+void
+uni_print_flag(const char *s, struct unicx *cx)
+{
+ doprefix(cx, s);
+}
+
+
+/*
+ * Start a deeper level of indendation. If multiline is in effect,
+ * we end the current line.
+ */
+void
+uni_print_push_prefix(const char *prefix, struct unicx *cx)
+{
+ if (cx->nprefix < PRINT_NPREFIX)
+ cx->prefix[cx->nprefix++] = prefix;
+}
+void
+uni_print_pop_prefix(struct unicx *cx)
+{
+ if (cx->nprefix > 0)
+ cx->nprefix--;
+}
+
+void
+uni_print_tbl(const char *entry, u_int val, const struct uni_print_tbl *tbl,
+ struct unicx *cx)
+{
+ if (entry)
+ uni_entry(entry, cx);
+ while (tbl->name) {
+ if (tbl->val == val) {
+ uni_printf(cx, "%s", tbl->name);
+ return;
+ }
+ tbl++;
+ }
+ uni_printf(cx, "ERROR(0x%x)", val);
+}
+
+void
+uni_print_entry(struct unicx *cx, const char *e, const char *fmt, ...)
+{
+ u_int n;
+ va_list ap;
+
+ uni_entry(e, cx);
+
+ if (cx->bufsiz > 1) {
+ va_start(ap, fmt);
+ n = vsnprintf(cx->buf, cx->bufsiz, fmt, ap);
+ va_end(ap);
+ if (n > 0) {
+ if (n < cx->bufsiz) {
+ cx->bufsiz -= n;
+ cx->buf += n;
+ } else {
+ cx->buf += cx->bufsiz - 1;
+ cx->bufsiz = 1;
+ }
+ }
+ *cx->buf = '\0';
+ }
+}
+
+/**********************************************************************/
+/*
+ * Printing information elements.
+ */
+static int
+uni_print_iehdr(const char *name, struct uni_iehdr *h, struct unicx *cx)
+{
+ static const struct uni_print_tbl act_tab[] = {
+ MKT(UNI_IEACT_CLEAR, clear),
+ MKT(UNI_IEACT_IGNORE, ignore),
+ MKT(UNI_IEACT_REPORT, report),
+ MKT(UNI_IEACT_MSG_IGNORE, ignore-msg),
+ MKT(UNI_IEACT_MSG_REPORT, report-msg),
+ MKT(UNI_IEACT_DEFAULT, default),
+ EOT()
+ };
+ static const struct uni_print_tbl cod_tab[] = {
+ MKT(UNI_CODING_ITU, itut),
+ MKT(UNI_CODING_NET, atmf),
+ EOT()
+ };
+
+ uni_print_entry(cx, name, "(");
+ uni_print_tbl(NULL, h->act, act_tab, cx);
+ uni_putc(',', cx);
+ uni_print_tbl(NULL, h->coding, cod_tab, cx);
+ if(cx->pnni && h->pass)
+ uni_printf(cx, ",pass");
+ if(IE_ISEMPTY(*(struct uni_ie_aal *)h)) {
+ uni_printf(cx, ",empty)");
+ uni_print_eol(cx);
+ return 1;
+ }
+ if(IE_ISERROR(*(struct uni_ie_aal *)h)) {
+ uni_printf(cx, ",error)");
+ uni_print_eol(cx);
+ return 1;
+ }
+
+ uni_putc(')', cx);
+
+ uni_print_push_prefix(name, cx);
+ uni_print_eol(cx);
+ cx->indent++;
+
+ return 0;
+}
+
+static void
+uni_print_ieend(struct unicx *cx)
+{
+ uni_print_pop_prefix(cx);
+ uni_print_eol(cx);
+ cx->indent--;
+}
+
+void
+uni_print_ie_internal(enum uni_ietype code, const union uni_ieall *ie,
+ struct unicx *cx)
+{
+ const struct iedecl *iedecl;
+
+ if((iedecl = GET_IEDECL(code, ie->h.coding)) != NULL)
+ (*iedecl->print)(ie, cx);
+}
+
+void
+uni_print_ie(char *buf, size_t size, enum uni_ietype code,
+ const union uni_ieall *ie, struct unicx *cx)
+{
+ uni_print_init(buf, size, cx);
+ uni_print_ie_internal(code, ie, cx);
+}
+
+int
+uni_check_ie(enum uni_ietype code, union uni_ieall *ie, struct unicx *cx)
+{
+ const struct iedecl *iedecl = GET_IEDECL(code, ie->h.coding);
+
+ if (iedecl != NULL)
+ return (iedecl->check(ie, cx));
+ else
+ return (-1);
+}
+
+/*
+ * Decode a information element header.
+ * Returns -1 if the message is too short.
+ * Strip the header from the message.
+ * The header is stripped, even if it is too short.
+ */
+int
+uni_decode_ie_hdr(enum uni_ietype *ietype, struct uni_iehdr *hdr,
+ struct uni_msg *msg, struct unicx *cx, u_int *ielen)
+{
+ u_int len;
+
+ *ietype = (enum uni_ietype)0;
+ *ielen = 0;
+ hdr->present = 0;
+ hdr->coding = UNI_CODING_ITU;
+ hdr->act = UNI_IEACT_DEFAULT;
+
+ if ((len = uni_msg_len(msg)) == 0)
+ return (-1);
+
+ *ietype = *msg->b_rptr++;
+
+ if (--len == 0)
+ return (-1);
+
+ hdr->coding = (*msg->b_rptr >> 5) & 3;
+ hdr->present = 0;
+
+ switch (*msg->b_rptr & 0x17) {
+
+ case 0x10: case 0x11: case 0x12:
+ case 0x15: case 0x16:
+ hdr->act = *msg->b_rptr & 0x7;
+ break;
+
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ hdr->act = UNI_IEACT_DEFAULT;
+ break;
+
+ default:
+ /* Q.2931 5.7.2 last sentence */
+ hdr->act = UNI_IEACT_REPORT;
+ break;
+ }
+ if (cx->pnni && (*msg->b_rptr & 0x08))
+ hdr->pass = 1;
+ else
+ hdr->pass = 0;
+ msg->b_rptr++;
+
+ if (--len == 0) {
+ hdr->present = UNI_IE_ERROR | UNI_IE_PRESENT;
+ return (-1);
+ }
+
+ if (len < 2) {
+ msg->b_rptr += len;
+ hdr->present = UNI_IE_ERROR | UNI_IE_PRESENT;
+ return (-1);
+ }
+
+ *ielen = *msg->b_rptr++ << 8;
+ *ielen |= *msg->b_rptr++;
+
+ return (0);
+}
+
+/*
+ * Decode the body of an information element.
+ */
+int
+uni_decode_ie_body(enum uni_ietype ietype, union uni_ieall *ie,
+ struct uni_msg *msg, u_int ielen, struct unicx *cx)
+{
+ const struct iedecl *iedecl;
+ u_char *end;
+ int ret;
+
+ if (ielen > uni_msg_len(msg)) {
+ /*
+ * Information element too long -> content error.
+ * Q.2931 5.6.8.2
+ */
+ msg->b_rptr = msg->b_wptr;
+ ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
+ return (-1);
+ }
+
+ if ((iedecl = GET_IEDECL(ietype, ie->h.coding)) == NULL) {
+ /*
+ * entirly unknown IE.
+ * Q.2931 5.6.8.1
+ */
+ msg->b_rptr += ielen;
+ ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
+ return (-1);
+ }
+
+ if (ielen > iedecl->maxlen) {
+ /*
+ * Information element too long -> content error.
+ * Q.2931 5.6.8.2
+ */
+ msg->b_rptr += iedecl->maxlen;
+ ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
+ return (-1);
+ }
+
+ end = msg->b_rptr + ielen;
+ ret = (*iedecl->decode)(ie, msg, ielen, cx);
+ msg->b_rptr = end;
+
+ return (ret);
+}
+
+int
+uni_encode_ie(enum uni_ietype code, struct uni_msg *msg, union uni_ieall *ie,
+ struct unicx *cx)
+{
+ const struct iedecl *iedecl = GET_IEDECL(code, ie->h.coding);
+
+ if (iedecl == NULL)
+ return (-1);
+ return (iedecl->encode(msg, ie, cx));
+}
+
+int
+uni_encode_ie_hdr(struct uni_msg *msg, enum uni_ietype type,
+ struct uni_iehdr *h, u_int len, struct unicx *cx)
+{
+ u_char byte;
+
+ (void)uni_msg_ensure(msg, 4 + len);
+ *msg->b_wptr++ = type;
+
+ byte = 0x80 | (h->coding << 5);
+ if(h->act != UNI_IEACT_DEFAULT)
+ byte |= 0x10 | (h->act & 7);
+ if(cx->pnni)
+ byte |= h->pass << 3;
+ *msg->b_wptr++ = byte;
+
+ if(h->present & UNI_IE_EMPTY) {
+ *msg->b_wptr++ = 0;
+ *msg->b_wptr++ = 4;
+ return -1;
+ }
+ *msg->b_wptr++ = 0;
+ *msg->b_wptr++ = 0;
+
+ return 0;
+}
+
+/*
+ * Printing messages.
+ */
+static void
+uni_print_cref_internal(const struct uni_cref *cref, struct unicx *cx)
+{
+ uni_print_entry(cx, "cref", "%d.", cref->flag);
+ if (cref->cref == CREF_GLOBAL)
+ uni_printf(cx, "GLOBAL");
+ else if (cref->cref == CREF_DUMMY)
+ uni_printf(cx, "DUMMY");
+ else
+ uni_printf(cx, "%d", cref->cref);
+}
+void
+uni_print_cref(char *str, size_t len, const struct uni_cref *cref,
+ struct unicx *cx)
+{
+ uni_print_init(str, len, cx);
+ uni_print_cref_internal(cref, cx);
+}
+
+static void
+uni_print_msghdr_internal(const struct uni_msghdr *hdr, struct unicx *cx)
+{
+ static const struct uni_print_tbl tab[] = {
+ MKT(UNI_MSGACT_CLEAR, clear),
+ MKT(UNI_MSGACT_IGNORE, ignore),
+ MKT(UNI_MSGACT_REPORT, report),
+ MKT(UNI_MSGACT_DEFAULT, default),
+ EOT()
+ };
+
+ uni_print_cref_internal(&hdr->cref, cx);
+ uni_print_tbl("act", hdr->act, tab, cx);
+ if (cx->pnni)
+ uni_print_entry(cx, "pass", "%s", hdr->pass ? "yes" : "no");
+}
+
+void
+uni_print_msghdr(char *str, size_t len, const struct uni_msghdr *hdr,
+ struct unicx *cx)
+{
+ uni_print_init(str, len, cx);
+ uni_print_msghdr_internal(hdr, cx);
+}
+
+
+static void
+uni_print_internal(const struct uni_all *msg, struct unicx *cx)
+{
+ uni_entry("mtype", cx);
+ if(msg->mtype >= 256 || uni_msgtable[msg->mtype] == NULL) {
+ uni_printf(cx, "0x%02x(ERROR)", msg->mtype);
+ } else {
+ uni_printf(cx, "%s", uni_msgtable[msg->mtype]->name);
+ uni_print_msghdr_internal(&msg->u.hdr, cx);
+ cx->indent++;
+ uni_print_eol(cx);
+ (*uni_msgtable[msg->mtype]->print)(&msg->u, cx);
+ cx->indent--;
+ }
+
+ if(cx->multiline == 0)
+ uni_printf(cx, "\n");
+}
+
+void
+uni_print(char *buf, size_t size, const struct uni_all *all, struct unicx *cx)
+{
+ uni_print_init(buf, size, cx);
+ uni_print_internal(all, cx);
+}
+
+static void
+uni_print_msg_internal(u_int mtype, const union uni_msgall *msg,
+ struct unicx *cx)
+{
+
+ uni_entry("mtype", cx);
+ if (mtype >= 256 || uni_msgtable[mtype] == NULL) {
+ uni_printf(cx, "0x%02x(ERROR)", mtype);
+ } else {
+ uni_printf(cx, "%s", uni_msgtable[mtype]->name);
+ uni_print_msghdr_internal(&msg->hdr, cx);
+ cx->indent++;
+ uni_print_eol(cx);
+ (*uni_msgtable[mtype]->print)(msg, cx);
+ cx->indent--;
+ }
+
+ if(cx->multiline == 0)
+ uni_printf(cx, "\n");
+}
+
+void
+uni_print_msg(char *buf, size_t size, u_int mtype, const union uni_msgall *all,
+ struct unicx *cx)
+{
+ uni_print_init(buf, size, cx);
+ uni_print_msg_internal(mtype, all, cx);
+}
+
+void
+uni_print_cx(char *buf, size_t size, struct unicx *cx)
+{
+ static const char *acttab[] = {
+ "clr", /* 0x00 */
+ "ign", /* 0x01 */
+ "rep", /* 0x02 */
+ "x03", /* 0x03 */
+ "x04", /* 0x04 */
+ "mig", /* 0x05 */
+ "mrp", /* 0x06 */
+ "x07", /* 0x07 */
+ "def", /* 0x08 */
+ };
+
+ static const char *errtab[] = {
+ [UNI_IERR_UNK] = "unk", /* unknown IE */
+ [UNI_IERR_LEN] = "len", /* length error */
+ [UNI_IERR_BAD] = "bad", /* content error */
+ [UNI_IERR_ACC] = "acc", /* access element discarded */
+ [UNI_IERR_MIS] = "mis", /* missing IE */
+ };
+
+ u_int i;
+
+ uni_print_init(buf, size, cx);
+
+ uni_printf(cx, "q2932 %d\n", cx->q2932);
+ uni_printf(cx, "pnni %d\n", cx->pnni);
+ uni_printf(cx, "git_hard %d\n", cx->git_hard);
+ uni_printf(cx, "bearer_hard %d\n", cx->bearer_hard);
+ uni_printf(cx, "cause_hard %d\n", cx->cause_hard);
+
+ uni_printf(cx, "multiline %d\n", cx->multiline);
+ uni_printf(cx, "tabsiz %d\n", cx->tabsiz);
+
+ uni_printf(cx, "errcnt %d (", cx->errcnt);
+ for(i = 0; i < cx->errcnt; i++) {
+ uni_printf(cx, "%02x[%s,%s%s]", cx->err[i].ie,
+ errtab[cx->err[i].err], acttab[cx->err[i].act],
+ cx->err[i].man ? ",M" : "");
+ if(i != cx->errcnt - 1)
+ uni_putc(' ', cx);
+ }
+ uni_printf(cx, ")\n");
+}
+
+#include <netnatm/msg/uni_ietab.h>
+
+/*********************************************************************
+ *
+ * Cause
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 69 (just a pointer to Q.2610)
+ * Q.2610 (this is a small diff to Q.850)
+ * Q.850 !!
+ * UNI4.0 pp. 15
+ * PNNI1.0 p. 198
+ *
+ * ITU-T and NET coding for different values.
+ */
+static const struct causetab {
+ const char *str;
+ enum uni_diag diag;
+} itu_causes[128] = {
+
+#define D(NAME,VAL,DIAG,STD,STR) [UNI_CAUSE_##NAME] = { STR, UNI_DIAG_##DIAG },
+#define N(NAME,VAL,DIAG,STD,STR)
+
+UNI_DECLARE_CAUSE_VALUES
+
+#undef D
+#undef N
+
+}, net_causes[128] = {
+
+#define D(NAME,VAL,DIAG,STD,STR)
+#define N(NAME,VAL,DIAG,STD,STR) [UNI_CAUSE_##NAME] = { STR, UNI_DIAG_##DIAG },
+
+UNI_DECLARE_CAUSE_VALUES
+
+#undef D
+#undef N
+
+};
+
+enum uni_diag
+uni_diag(enum uni_cause cause, enum uni_coding code)
+{
+ if ((int)cause >= 128)
+ return (UNI_DIAG_NONE);
+
+ if (code == UNI_CODING_NET)
+ if (net_causes[cause].str != NULL)
+ return (net_causes[cause].diag);
+ if (itu_causes[cause].str != NULL)
+ return (itu_causes[cause].diag);
+ return (UNI_DIAG_NONE);
+}
+
+/**********************************************************************/
+
+static void
+print_cause(struct unicx *cx, struct uni_ie_cause *ie,
+ const struct causetab *tab1, const struct causetab *tab2)
+{
+ static const struct uni_print_tbl loc_tbl[] = {
+ MKT(UNI_CAUSE_LOC_USER, user),
+ MKT(UNI_CAUSE_LOC_PRIVLOC, priv-net:loc-user),
+ MKT(UNI_CAUSE_LOC_PUBLOC, pub-net:loc-user),
+ MKT(UNI_CAUSE_LOC_TRANSIT, transit-net),
+ MKT(UNI_CAUSE_LOC_PUBREM, pub-net:rem-user),
+ MKT(UNI_CAUSE_LOC_PRIVREM, priv-net:rem-user),
+ MKT(UNI_CAUSE_LOC_INTERNAT, int-net),
+ MKT(UNI_CAUSE_LOC_BEYOND, beyond),
+ EOT()
+ };
+ static const struct uni_print_tbl pu_tbl[] = {
+ MKT(UNI_CAUSE_PU_PROVIDER, provider),
+ MKT(UNI_CAUSE_PU_USER, user),
+ EOT()
+ };
+ static const struct uni_print_tbl na_tbl[] = {
+ MKT(UNI_CAUSE_NA_NORMAL, normal),
+ MKT(UNI_CAUSE_NA_ABNORMAL, abnormal),
+ EOT()
+ };
+ static const struct uni_print_tbl cond_tbl[] = {
+ MKT(UNI_CAUSE_COND_UNKNOWN, unknown),
+ MKT(UNI_CAUSE_COND_PERM, permanent),
+ MKT(UNI_CAUSE_COND_TRANS, transient),
+ EOT()
+ };
+ static const struct uni_print_tbl rej_tbl[] = {
+ MKT(UNI_CAUSE_REASON_USER, user),
+ MKT(UNI_CAUSE_REASON_IEMISS, ie-missing),
+ MKT(UNI_CAUSE_REASON_IESUFF, ie-not-suff),
+ EOT()
+ };
+ char buf[100], *s;
+ u_int i;
+
+ if (uni_print_iehdr("cause", &ie->h, cx))
+ return;
+
+ if ((int)ie->cause < 128 && tab1[ie->cause].str)
+ strcpy(buf, tab1[ie->cause].str);
+ else if ((int)ie->cause < 128 && tab2 != NULL && tab2[ie->cause].str != NULL)
+ strcpy(buf, tab2[ie->cause].str);
+ else {
+ sprintf(buf, "UNKNOWN-%u", ie->cause);
+ }
+
+ for (s = buf; *s != '\0'; s++)
+ if (*s == ' ')
+ *s = '_';
+ uni_print_entry(cx, "cause", "%s", buf);
+
+ uni_print_tbl("loc", ie->loc, loc_tbl, cx);
+
+ if (ie->h.present & UNI_CAUSE_COND_P) {
+ uni_print_tbl("pu", ie->u.cond.pu, pu_tbl, cx);
+ uni_print_tbl("na", ie->u.cond.na, na_tbl, cx);
+ uni_print_tbl("condition", ie->u.cond.cond, cond_tbl, cx);
+ }
+ if (ie->h.present & UNI_CAUSE_REJ_P) {
+ uni_print_tbl("reject", ie->u.rej.reason, rej_tbl, cx);
+ }
+ if (ie->h.present & UNI_CAUSE_REJ_USER_P) {
+ uni_print_entry(cx, "user", "%u", ie->u.rej.user);
+ }
+ if (ie->h.present & UNI_CAUSE_REJ_IE_P) {
+ uni_print_entry(cx, "ie", "%u", ie->u.rej.ie);
+ }
+ if (ie->h.present & UNI_CAUSE_IE_P) {
+ uni_print_entry(cx, "ie", "(");
+ for (i = 0; i < ie->u.ie.len; i++) {
+ if (i)
+ uni_putc(',', cx);
+ uni_printf(cx, "0x%02x", ie->u.ie.ie[i]);
+ }
+ uni_putc(')', cx);
+ }
+ if (ie->h.present & UNI_CAUSE_TRAFFIC_P) {
+ uni_print_entry(cx, "traffic", "(");
+ for (i = 0; i < ie->u.traffic.len; i++) {
+ if (i)
+ uni_putc(',', cx);
+ uni_printf(cx, "0x%02x", ie->u.traffic.traffic[i]);
+ }
+ uni_putc(')', cx);
+ }
+ if (ie->h.present & UNI_CAUSE_VPCI_P) {
+ uni_print_entry(cx, "vpci", "(%u,%u)", ie->u.vpci.vpci, ie->u.vpci.vci);
+ }
+ if (ie->h.present & UNI_CAUSE_MTYPE_P) {
+ uni_print_entry(cx, "mtype", "%u", ie->u.mtype);
+ }
+ if (ie->h.present & UNI_CAUSE_TIMER_P) {
+ for (i = 0, s = buf; i < 3; i++) {
+ if (ie->u.timer[i] < ' ') {
+ *s++ = '^';
+ *s++ = ie->u.timer[i] + '@';
+ } else if (ie->u.timer[i] <= '~')
+ *s++ = ie->u.timer[i];
+ else {
+ *s++ = '\\';
+ *s++ = ie->u.timer[i] / 0100 + '0';
+ *s++ = (ie->u.timer[i] % 0100) / 010 + '0';
+ *s++ = ie->u.timer[i] % 010 + '0';
+ }
+ }
+ *s++ = '\0';
+ uni_print_entry(cx, "timer", "\"%s\"", buf);
+ }
+ if (ie->h.present & UNI_CAUSE_TNS_P) {
+ uni_print_eol(cx);
+ uni_print_ie_internal(UNI_IE_TNS, (union uni_ieall *)&ie->u.tns, cx);
+ }
+ if (ie->h.present & UNI_CAUSE_NUMBER_P) {
+ uni_print_eol(cx);
+ uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&ie->u.number, cx);
+ }
+ if (ie->h.present & UNI_CAUSE_ATTR_P) {
+ uni_print_entry(cx, "attr", "(");
+ for (i = 0; i < ie->u.attr.nattr; i++) {
+ uni_printf(cx, "(%u", ie->u.attr.attr[i][0]);
+ if (!(ie->u.attr.attr[i][0] & 0x80)) {
+ uni_printf(cx, ",%u", ie->u.attr.attr[i][1]);
+ if (!(ie->u.attr.attr[i][1] & 0x80))
+ uni_printf(cx, ",%u",
+ ie->u.attr.attr[i][2]);
+ }
+ uni_putc(')', cx);
+ }
+ }
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_PRINT(itu, cause)
+{
+ print_cause(cx, ie, itu_causes, NULL);
+}
+DEF_IE_PRINT(net, cause)
+{
+ print_cause(cx, ie, net_causes, itu_causes);
+}
+
+const char *
+uni_ie_cause2str(enum uni_coding coding, u_int cause)
+{
+ if (cause < 128) {
+ if (coding == UNI_CODING_ITU)
+ return (itu_causes[cause].str);
+ if (coding == UNI_CODING_NET) {
+ if (net_causes[cause].str != NULL)
+ return (net_causes[cause].str);
+ return (itu_causes[cause].str);
+ }
+ }
+ return (NULL);
+}
+
+/**********************************************************************/
+
+static int
+check_cause(struct uni_ie_cause *ie, struct unicx *cx,
+ const struct causetab *tab1, const struct causetab *tab2)
+{
+ static const u_int mask =
+ UNI_CAUSE_COND_P | UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P |
+ UNI_CAUSE_REJ_IE_P | UNI_CAUSE_IE_P | UNI_CAUSE_TRAFFIC_P |
+ UNI_CAUSE_VPCI_P | UNI_CAUSE_MTYPE_P | UNI_CAUSE_TIMER_P |
+ UNI_CAUSE_TNS_P | UNI_CAUSE_NUMBER_P | UNI_CAUSE_ATTR_P |
+ UNI_CAUSE_PARAM_P;
+
+ const struct causetab *ptr;
+
+ if ((int)ie->cause >= 128)
+ return (-1);
+
+ switch (ie->loc) {
+ default:
+ return (-1);
+
+ case UNI_CAUSE_LOC_USER:
+ case UNI_CAUSE_LOC_PRIVLOC:
+ case UNI_CAUSE_LOC_PUBLOC:
+ case UNI_CAUSE_LOC_TRANSIT:
+ case UNI_CAUSE_LOC_PUBREM:
+ case UNI_CAUSE_LOC_PRIVREM:
+ case UNI_CAUSE_LOC_INTERNAT:
+ case UNI_CAUSE_LOC_BEYOND:
+ break;
+ }
+
+ if (tab1[ie->cause].str != NULL)
+ ptr = &tab1[ie->cause];
+ else if (tab2 != NULL && tab2[ie->cause].str != NULL)
+ ptr = &tab2[ie->cause];
+ else
+ return (cx->cause_hard ? -1 : 0);
+
+ switch (ptr->diag) {
+
+ case UNI_DIAG_NONE:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_COND:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_COND_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_REJ:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_REJ_P:
+ case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P:
+ case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_IE_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_CRATE:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_TRAFFIC_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_IE:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_IE_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_CHANID:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_VPCI_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_MTYPE:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_MTYPE_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_TIMER:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_TIMER_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_TNS:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_TNS_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_NUMBER:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_NUMBER_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_ATTR:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_ATTR_P:
+ break;
+ }
+ break;
+
+ case UNI_DIAG_PARAM:
+ switch (ie->h.present & mask) {
+ default:
+ if (cx->cause_hard)
+ return (-1);
+ break;
+
+ case 0:
+ case UNI_CAUSE_PARAM_P:
+ break;
+ }
+ break;
+ }
+
+ if (ie->h.present & UNI_CAUSE_COND_P) {
+ switch (ie->u.cond.pu) {
+ default:
+ return (-1);
+
+ case UNI_CAUSE_PU_PROVIDER:
+ case UNI_CAUSE_PU_USER:
+ break;
+ }
+ switch (ie->u.cond.na) {
+ default:
+ return (-1);
+
+ case UNI_CAUSE_NA_NORMAL:
+ case UNI_CAUSE_NA_ABNORMAL:
+ break;
+ }
+ switch (ie->u.cond.cond) {
+ default:
+ return (-1);
+
+ case UNI_CAUSE_COND_UNKNOWN:
+ case UNI_CAUSE_COND_PERM:
+ case UNI_CAUSE_COND_TRANS:
+ break;
+ }
+ }
+ if (ie->h.present & UNI_CAUSE_REJ_P) {
+ switch (ie->u.rej.reason) {
+ default:
+ return (-1);
+
+ case UNI_CAUSE_REASON_USER:
+ switch (ie->h.present & mask) {
+ default:
+ return (-1);
+
+ case UNI_CAUSE_REJ_P:
+ case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P:
+ break;
+ }
+ break;
+
+ case UNI_CAUSE_REASON_IEMISS:
+ case UNI_CAUSE_REASON_IESUFF:
+ switch (ie->h.present & mask) {
+ default:
+ return (-1);
+
+ case UNI_CAUSE_REJ_P:
+ case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_IE_P:
+ break;
+ }
+ break;
+ }
+ }
+ if (ie->h.present & UNI_CAUSE_IE_P) {
+ if (ie->u.ie.len == 0 || ie->u.ie.len > UNI_CAUSE_IE_N)
+ return (-1);
+ }
+ if (ie->h.present & UNI_CAUSE_TRAFFIC_P) {
+ if (ie->u.traffic.len == 0 ||
+ ie->u.traffic.len > UNI_CAUSE_TRAFFIC_N)
+ return (-1);
+ }
+
+ if (ie->h.present & UNI_CAUSE_TNS_P) {
+ if (uni_check_ie(UNI_IE_TNS, (union uni_ieall *)&ie->u.tns, cx))
+ return (-1);
+ }
+ if (ie->h.present & UNI_CAUSE_NUMBER_P) {
+ if(uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&ie->u.number, cx))
+ return (-1);
+ }
+ if (ie->h.present & UNI_CAUSE_ATTR_P) {
+ if(ie->u.attr.nattr > UNI_CAUSE_ATTR_N || ie->u.attr.nattr == 0)
+ return (-1);
+ }
+ if (ie->h.present & UNI_CAUSE_PARAM_P) {
+ UNUSED(cx);
+ }
+
+ return (0);
+}
+
+DEF_IE_CHECK(itu, cause)
+{
+ return (check_cause(ie, cx, itu_causes, NULL));
+}
+DEF_IE_CHECK(net, cause)
+{
+ return (check_cause(ie, cx, net_causes, itu_causes));
+}
+/**********************************************************************/
+
+static int
+encode_cause(struct uni_msg *msg, struct uni_ie_cause *ie, struct unicx *cx)
+{
+ u_int i;
+
+ START_IE(cause, UNI_IE_CAUSE, 30);
+
+ if (IE_ISERROR(*ie)) {
+ APP_BYTE(msg, 0x00 | ie->loc);
+ } else {
+ APP_BYTE(msg, 0x80 | ie->loc);
+ }
+ APP_BYTE(msg, 0x80 | ie->cause);
+
+ if (ie->h.present & UNI_CAUSE_COND_P)
+ APP_BYTE(msg, 0x80 | (ie->u.cond.pu << 3) |
+ (ie->u.cond.na << 2) | ie->u.cond.cond);
+
+ else if (ie->h.present & UNI_CAUSE_REJ_P) {
+ APP_BYTE(msg, 0x80 | (ie->u.rej.reason << 2) | ie->u.rej.cond);
+ if (ie->h.present & UNI_CAUSE_REJ_USER_P)
+ APP_BYTE(msg, ie->u.rej.user);
+ else if (ie->h.present & UNI_CAUSE_REJ_IE_P)
+ APP_BYTE(msg, ie->u.rej.ie);
+
+ } else if(ie->h.present & UNI_CAUSE_IE_P)
+ APP_BUF(msg, ie->u.ie.ie, ie->u.ie.len);
+
+ else if (ie->h.present & UNI_CAUSE_TRAFFIC_P)
+ APP_BUF(msg, ie->u.traffic.traffic, ie->u.traffic.len);
+
+ else if (ie->h.present & UNI_CAUSE_VPCI_P) {
+ APP_BYTE(msg, (ie->u.vpci.vpci >> 8));
+ APP_BYTE(msg, (ie->u.vpci.vpci >> 0));
+ APP_BYTE(msg, (ie->u.vpci.vci >> 8));
+ APP_BYTE(msg, (ie->u.vpci.vci >> 0));
+
+ } else if (ie->h.present & UNI_CAUSE_MTYPE_P)
+ APP_BYTE(msg, ie->u.mtype);
+
+ else if (ie->h.present & UNI_CAUSE_TIMER_P) {
+ APP_BYTE(msg, ie->u.timer[0]);
+ APP_BYTE(msg, ie->u.timer[1]);
+ APP_BYTE(msg, ie->u.timer[2]);
+
+ } else if (ie->h.present & UNI_CAUSE_TNS_P)
+ uni_encode_ie(UNI_IE_TNS, msg,
+ (union uni_ieall *)&ie->u.tns, cx);
+
+ else if (ie->h.present & UNI_CAUSE_NUMBER_P)
+ uni_encode_ie(UNI_IE_CALLED, msg,
+ (union uni_ieall *)&ie->u.number, cx);
+
+ else if (ie->h.present & UNI_CAUSE_ATTR_P) {
+ for (i = 0; i < ie->u.attr.nattr; i++) {
+ APP_BYTE(msg, ie->u.attr.attr[i][0]);
+ if (!ie->u.attr.attr[i][0]) {
+ APP_BYTE(msg, ie->u.attr.attr[i][1]);
+ if (!ie->u.attr.attr[i][1])
+ APP_BYTE(msg, ie->u.attr.attr[i][2]);
+ }
+ }
+ } else if (ie->h.present & UNI_CAUSE_PARAM_P)
+ APP_BYTE(msg, ie->u.param);
+
+ SET_IE_LEN(msg);
+
+ return (0);
+}
+
+DEF_IE_ENCODE(itu, cause)
+{
+ return encode_cause(msg, ie, cx);
+}
+DEF_IE_ENCODE(net, cause)
+{
+ return encode_cause(msg, ie, cx);
+}
+
+/**********************************************************************/
+
+static int
+decode_cause(struct uni_ie_cause *ie, struct uni_msg *msg, u_int ielen,
+ struct unicx *cx, const struct causetab *tab1, const struct causetab *tab2)
+{
+ u_char c;
+ const struct causetab *ptr;
+ enum uni_ietype ietype;
+ u_int xielen;
+
+ IE_START(;);
+
+ if(ielen < 2 || ielen > 30)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ ielen--;
+ if(!(c & 0x80))
+ goto rej;
+ ie->loc = c & 0xf;
+
+ c = *msg->b_rptr++;
+ ielen--;
+ if(!(c & 0x80))
+ goto rej;
+ ie->cause = c & 0x7f;
+
+ if(tab1[ie->cause].str != NULL)
+ ptr = &tab1[ie->cause];
+ else if(tab2 != NULL && tab2[ie->cause].str != NULL)
+ ptr = &tab2[ie->cause];
+ else {
+ ptr = NULL;
+ ielen = 0; /* ignore diags */
+ }
+
+ if(ielen) {
+ switch(ptr->diag) {
+
+ case UNI_DIAG_NONE:
+ break;
+
+ case UNI_DIAG_COND:
+ if(ielen < 1)
+ goto rej;
+ c = *msg->b_rptr++;
+ ielen--;
+
+ ie->h.present |= UNI_CAUSE_COND_P;
+ ie->u.cond.pu = (c >> 3) & 1;
+ ie->u.cond.na = (c >> 2) & 1;
+ ie->u.cond.cond = c & 3;
+
+ if(!(c & 0x80))
+ goto rej;
+ break;
+
+ case UNI_DIAG_REJ:
+ if(ielen < 1)
+ goto rej;
+ c = *msg->b_rptr++;
+ ielen--;
+
+ ie->h.present |= UNI_CAUSE_REJ_P;
+ ie->u.rej.reason = (c >> 2) & 0x1f;
+ ie->u.rej.cond = c & 3;
+
+ if(!(c & 0x80))
+ goto rej;
+
+ if(ielen > 0) {
+ c = *msg->b_rptr++;
+ ielen--;
+
+ switch(ie->u.rej.reason) {
+
+ case UNI_CAUSE_REASON_USER:
+ ie->h.present |= UNI_CAUSE_REJ_USER_P;
+ ie->u.rej.user = c;
+ break;
+
+ case UNI_CAUSE_REASON_IEMISS:
+ case UNI_CAUSE_REASON_IESUFF:
+ ie->h.present |= UNI_CAUSE_REJ_IE_P;
+ ie->u.rej.ie = c;
+ break;
+ }
+ }
+ break;
+
+ case UNI_DIAG_CRATE:
+ ie->h.present |= UNI_CAUSE_TRAFFIC_P;
+ while(ielen && ie->u.traffic.len < UNI_CAUSE_TRAFFIC_N) {
+ ie->u.traffic.traffic[ie->u.traffic.len++] =
+ *msg->b_rptr++;
+ ielen--;
+ }
+ break;
+
+ case UNI_DIAG_IE:
+ ie->h.present |= UNI_CAUSE_IE_P;
+ while(ielen && ie->u.ie.len < UNI_CAUSE_IE_N) {
+ ie->u.ie.ie[ie->u.ie.len++] = *msg->b_rptr++;
+ ielen--;
+ }
+ break;
+
+ case UNI_DIAG_CHANID:
+ if(ielen < 4)
+ break;
+ ie->h.present |= UNI_CAUSE_VPCI_P;
+ ie->u.vpci.vpci = *msg->b_rptr++ << 8;
+ ie->u.vpci.vpci |= *msg->b_rptr++;
+ ie->u.vpci.vci = *msg->b_rptr++ << 8;
+ ie->u.vpci.vci |= *msg->b_rptr++;
+ ielen -= 4;
+ break;
+
+ case UNI_DIAG_MTYPE:
+ ie->h.present |= UNI_CAUSE_MTYPE_P;
+ ie->u.mtype = *msg->b_rptr++;
+ ielen--;
+ break;
+
+ case UNI_DIAG_TIMER:
+ if(ielen < 3)
+ break;
+ ie->h.present |= UNI_CAUSE_TIMER_P;
+ ie->u.timer[0] = *msg->b_rptr++;
+ ie->u.timer[1] = *msg->b_rptr++;
+ ie->u.timer[2] = *msg->b_rptr++;
+ ielen -= 3;
+ break;
+
+ case UNI_DIAG_TNS:
+ if(ielen < 4)
+ break;
+ if(uni_decode_ie_hdr(&ietype, &ie->u.tns.h, msg, cx, &xielen))
+ break;
+ if(ietype != UNI_IE_TNS)
+ break;
+ if(uni_decode_ie_body(ietype,
+ (union uni_ieall *)&ie->u.tns, msg, xielen, cx))
+ break;
+ ie->h.present |= UNI_CAUSE_TNS_P;
+ break;
+
+ case UNI_DIAG_NUMBER:
+ if(ielen < 4)
+ break;
+ if(uni_decode_ie_hdr(&ietype, &ie->u.number.h, msg, cx, &xielen))
+ break;
+ if(ietype != UNI_IE_CALLED)
+ break;
+ if(uni_decode_ie_body(ietype,
+ (union uni_ieall *)&ie->u.number, msg, xielen, cx))
+ break;
+ ie->h.present |= UNI_CAUSE_NUMBER_P;
+ break;
+
+ case UNI_DIAG_ATTR:
+ ie->h.present |= UNI_CAUSE_ATTR_P;
+ while(ielen > 0 && ie->u.attr.nattr < UNI_CAUSE_ATTR_N) {
+ c = *msg->b_rptr++;
+ ie->u.attr.attr[ie->u.attr.nattr][0] = c;
+ ielen--;
+ if(ielen > 0 && !(c & 0x80)) {
+ c = *msg->b_rptr++;
+ ie->u.attr.attr[ie->u.attr.nattr][1] = c;
+ ielen--;
+ if(ielen > 0 && !(c & 0x80)) {
+ c = *msg->b_rptr++;
+ ie->u.attr.attr[ie->u.attr.nattr][2] = c;
+ ielen--;
+ }
+ }
+ }
+ break;
+
+ case UNI_DIAG_PARAM:
+ ie->h.present |= UNI_CAUSE_PARAM_P;
+ ie->u.param = *msg->b_rptr++;
+ ielen--;
+ break;
+ }
+ }
+
+ IE_END(CAUSE);
+}
+
+DEF_IE_DECODE(itu, cause)
+{
+ return decode_cause(ie, msg, ielen, cx, itu_causes, NULL);
+}
+DEF_IE_DECODE(net, cause)
+{
+ return decode_cause(ie, msg, ielen, cx, net_causes, itu_causes);
+}
+
+/*********************************************************************
+ *
+ * Callstate
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 59...60
+ * UNI4.0 pp. 14
+ *
+ * Only ITU-T coding allowed.
+ */
+DEF_IE_PRINT(itu, callstate)
+{
+ static const struct uni_print_tbl tbl[] = {
+ MKT(UNI_CALLSTATE_U0, U0/N0/REST0),
+ MKT(UNI_CALLSTATE_U1, U1/N1),
+ MKT(UNI_CALLSTATE_U3, U3/N3),
+ MKT(UNI_CALLSTATE_U4, U4/N4),
+ MKT(UNI_CALLSTATE_U6, U6/N6),
+ MKT(UNI_CALLSTATE_U7, U7/N7),
+ MKT(UNI_CALLSTATE_U8, U8/N8),
+ MKT(UNI_CALLSTATE_U9, U9/N9),
+ MKT(UNI_CALLSTATE_U10, U10/N10),
+ MKT(UNI_CALLSTATE_U11, U11/N11),
+ MKT(UNI_CALLSTATE_U12, U12/N12),
+ MKT(UNI_CALLSTATE_REST1,REST1),
+ MKT(UNI_CALLSTATE_REST2,REST2),
+ MKT(UNI_CALLSTATE_U13, U13/N13),
+ MKT(UNI_CALLSTATE_U14, U14/N14),
+ EOT()
+ };
+
+ if(uni_print_iehdr("callstate", &ie->h, cx))
+ return;
+ uni_print_tbl("state", ie->state, tbl, cx);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, callstate)
+{
+ UNUSED(cx);
+
+ switch(ie->state) {
+ default:
+ return -1;
+
+ case UNI_CALLSTATE_U0:
+ case UNI_CALLSTATE_U1:
+ case UNI_CALLSTATE_U3:
+ case UNI_CALLSTATE_U4:
+ case UNI_CALLSTATE_U6:
+ case UNI_CALLSTATE_U7:
+ case UNI_CALLSTATE_U8:
+ case UNI_CALLSTATE_U9:
+ case UNI_CALLSTATE_U10:
+ case UNI_CALLSTATE_U11:
+ case UNI_CALLSTATE_U12:
+ case UNI_CALLSTATE_REST1:
+ case UNI_CALLSTATE_REST2:
+ case UNI_CALLSTATE_U13:
+ case UNI_CALLSTATE_U14:
+ break;
+ }
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, callstate)
+{
+ START_IE(callstate, UNI_IE_CALLSTATE, 1);
+
+ APP_BYTE(msg, ie->state);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, callstate)
+{
+ IE_START(;);
+
+ if(ielen != 1)
+ goto rej;
+
+ ie->state = *msg->b_rptr++ & 0x3f;
+ ielen--;
+
+ IE_END(CALLSTATE);
+}
+
+/*********************************************************************
+ *
+ * Facility Information.
+ *
+ * References for this IE are:
+ *
+ * Q.2932.1
+ *
+ * The standard allows only ROSE as protocol. We allow everything up to the
+ * maximum size.
+ *
+ * Only ITU-T coding allowed.
+ */
+DEF_IE_PRINT(itu, facility)
+{
+ u_int i;
+
+ if(uni_print_iehdr("facility", &ie->h, cx))
+ return;
+
+ if(ie->proto == UNI_FACILITY_ROSE)
+ uni_print_entry(cx, "proto", "rose");
+ else
+ uni_print_entry(cx, "proto", "0x%02x", ie->proto);
+
+ uni_print_entry(cx, "len", "%u", ie->len);
+ uni_print_entry(cx, "info", "(");
+ for(i = 0; i < ie->len; i++)
+ uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->apdu[i]);
+ uni_printf(cx, ")");
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, facility)
+{
+ UNUSED(cx);
+
+ if(ie->len > UNI_FACILITY_MAXAPDU)
+ return -1;
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, facility)
+{
+ START_IE(facility, UNI_IE_FACILITY, 1 + ie->len);
+
+ APP_BYTE(msg, ie->proto | 0x80);
+ APP_BUF(msg, ie->apdu, ie->len);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, facility)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen > UNI_FACILITY_MAXAPDU + 1 || ielen < 1)
+ goto rej;
+
+ ie->proto = (c = *msg->b_rptr++) & 0x1f;
+ ielen--;
+ if((c & 0xe0) != 0x80)
+ goto rej;
+
+ ie->len = ielen;
+ ielen = 0;
+ (void)memcpy(ie->apdu, msg->b_rptr, ie->len);
+ msg->b_rptr += ie->len;
+
+ IE_END(FACILITY);
+}
+
+/*********************************************************************
+ *
+ * Notification Indicator
+ *
+ * References for this IE are:
+ *
+ * Q.2931 p. 76
+ * UNI4.0 p. 17
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, notify)
+{
+ u_int i;
+
+ if(uni_print_iehdr("notify", &ie->h, cx))
+ return;
+ uni_print_entry(cx, "len", "%u", ie->len);
+ uni_print_entry(cx, "info", "(");
+ for(i = 0; i < ie->len; i++)
+ uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->notify[i]);
+ uni_printf(cx, ")");
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, notify)
+{
+ UNUSED(cx);
+
+ if(ie->len > UNI_NOTIFY_MAXLEN)
+ return -1;
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, notify)
+{
+ START_IE(notify, UNI_IE_NOTIFY, ie->len);
+
+ APP_BUF(msg, ie->notify, ie->len);
+ if (IE_ISERROR(*ie)) {
+ /* make it too long */
+ u_int i = ie->len;
+
+ while (i < UNI_NOTIFY_MAXLEN + 1) {
+ APP_BYTE(msg, 0x00);
+ i++;
+ }
+ }
+
+ SET_IE_LEN(msg);
+ return (0);
+}
+
+DEF_IE_DECODE(itu, notify)
+{
+ IE_START(;);
+
+ if (ielen > UNI_NOTIFY_MAXLEN || ielen < 1)
+ goto rej;
+
+ ie->len = ielen;
+ ielen = 0;
+ (void)memcpy(ie->notify, msg->b_rptr, ie->len);
+ msg->b_rptr += ie->len;
+
+ IE_END(NOTIFY);
+}
+
+/*********************************************************************
+ *
+ * End-to-end transit delay.
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 70...71
+ * UNI4.0 pp. 69...70
+ * PNNI1.0 pp. 198...200
+ *
+ * Not clear, whether the new indicator should be used with NET coding or
+ * not.
+ *
+ * Only ITU-T coding allowed.
+ */
+
+static void
+print_eetd(struct uni_ie_eetd *ie, struct unicx *cx)
+{
+ if (uni_print_iehdr("eetd", &ie->h, cx))
+ return;
+
+ if (ie->h.present & UNI_EETD_CUM_P)
+ uni_print_entry(cx, "cum", "%u", ie->cumulative);
+ if (ie->h.present & UNI_EETD_MAX_P) {
+ if (ie->maximum == UNI_EETD_ANYMAX)
+ uni_print_entry(cx, "max", "any");
+ else
+ uni_print_entry(cx, "max", "%u", ie->maximum);
+ }
+ if (ie->h.present & UNI_EETD_PCTD_P)
+ uni_print_entry(cx, "pnni_cum", "%u", ie->pctd);
+ if (ie->h.present & UNI_EETD_PMTD_P)
+ uni_print_entry(cx, "pnni_max", "%u", ie->pmtd);
+ if (ie->h.present & UNI_EETD_NET_P)
+ uni_print_flag("netgen", cx);
+
+ uni_print_ieend(cx);
+}
+DEF_IE_PRINT(itu, eetd)
+{
+ print_eetd(ie, cx);
+}
+DEF_IE_PRINT(net, eetd)
+{
+ print_eetd(ie, cx);
+}
+
+DEF_IE_CHECK(itu, eetd)
+{
+
+ UNUSED(cx);
+
+ if (!(ie->h.present & UNI_EETD_CUM_P))
+ return (-1);
+ if (ie->h.present & (UNI_EETD_PMTD_P | UNI_EETD_PCTD_P))
+ return (-1);
+ return (0);
+}
+
+DEF_IE_CHECK(net, eetd)
+{
+
+ if (!cx->pnni) {
+ if (!(ie->h.present & UNI_EETD_CUM_P))
+ return (-1);
+ if (ie->h.present & (UNI_EETD_PMTD_P | UNI_EETD_PCTD_P))
+ return (-1);
+ } else {
+ if (ie->h.present & UNI_EETD_MAX_P)
+ return (-1);
+ if ((ie->h.present & UNI_EETD_CUM_P) &&
+ (ie->h.present & UNI_EETD_PCTD_P))
+ return (-1);
+ }
+ return (0);
+}
+
+DEF_IE_ENCODE(itu, eetd)
+{
+ START_IE(eetd, UNI_IE_EETD, 9);
+
+ if (ie->h.present & UNI_EETD_CUM_P) {
+ APP_BYTE(msg, UNI_EETD_CTD_ID);
+ APP_16BIT(msg, ie->cumulative);
+ }
+ if (ie->h.present & UNI_EETD_MAX_P) {
+ APP_BYTE(msg, UNI_EETD_MTD_ID);
+ APP_16BIT(msg, ie->maximum);
+ }
+ if (ie->h.present & UNI_EETD_PMTD_P) {
+ APP_BYTE(msg, UNI_EETD_PMTD_ID);
+ APP_24BIT(msg, ie->pmtd);
+ }
+ if (ie->h.present & UNI_EETD_PCTD_P) {
+ APP_BYTE(msg, UNI_EETD_PCTD_ID);
+ APP_24BIT(msg, ie->pctd);
+ }
+ if (ie->h.present & UNI_EETD_NET_P) {
+ APP_BYTE(msg, UNI_EETD_NET_ID);
+ }
+
+ SET_IE_LEN(msg);
+ return (0);
+}
+
+DEF_IE_ENCODE(net, eetd)
+{
+ return (uni_ie_encode_itu_eetd(msg, ie, cx));
+}
+
+DEF_IE_DECODE(itu, eetd)
+{
+ IE_START(;);
+
+ while (ielen > 0) {
+ switch (ielen--, *msg->b_rptr++) {
+
+ case UNI_EETD_CTD_ID:
+ if (ielen < 2)
+ goto rej;
+ ie->h.present |= UNI_EETD_CUM_P;
+ ie->cumulative = *msg->b_rptr++ << 8;
+ ie->cumulative |= *msg->b_rptr++;
+ ielen -= 2;
+ break;
+
+ case UNI_EETD_MTD_ID:
+ if (ielen < 2)
+ goto rej;
+ ie->h.present |= UNI_EETD_MAX_P;
+ ie->maximum = *msg->b_rptr++ << 8;
+ ie->maximum |= *msg->b_rptr++;
+ ielen -= 2;
+ break;
+
+ case UNI_EETD_PCTD_ID:
+ if (ielen < 3)
+ goto rej;
+ ie->h.present |= UNI_EETD_PCTD_P;
+ ie->pctd = *msg->b_rptr++ << 16;
+ ie->pctd |= *msg->b_rptr++ << 8;
+ ie->pctd |= *msg->b_rptr++;
+ ielen -= 3;
+ break;
+
+ case UNI_EETD_PMTD_ID:
+ if (ielen < 3)
+ goto rej;
+ ie->h.present |= UNI_EETD_PMTD_P;
+ ie->pmtd = *msg->b_rptr++ << 16;
+ ie->pmtd |= *msg->b_rptr++ << 8;
+ ie->pmtd |= *msg->b_rptr++;
+ ielen -= 3;
+ break;
+
+ case UNI_EETD_NET_ID:
+ ie->h.present |= UNI_EETD_NET_P;
+ break;
+
+ default:
+ goto rej;
+ }
+ }
+
+ IE_END(EETD);
+}
+DEF_IE_DECODE(net, eetd)
+{
+ return (uni_ie_decode_itu_eetd(ie, msg, ielen, cx));
+}
+
+/*********************************************************************
+ *
+ * Called address
+ * Called subaddress
+ * Calling address
+ * Calling subaddress
+ * Connected address
+ * Connected subaddress
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 60...68
+ * ...A4 pp. 27...36
+ * UNI4.0 pp. 14...15
+ * Q.2951 pp. 28...40
+ *
+ * It is assumed, that the coding of the addr arrays is ok.
+ *
+ * Only ITU-T coding allowed.
+ */
+
+static const struct uni_print_tbl screen_tbl[] = {
+ MKT(UNI_ADDR_SCREEN_NOT, no),
+ MKT(UNI_ADDR_SCREEN_PASSED, passed),
+ MKT(UNI_ADDR_SCREEN_FAILED, failed),
+ MKT(UNI_ADDR_SCREEN_NET, network),
+ EOT()
+};
+static const struct uni_print_tbl pres_tbl[] = {
+ MKT(UNI_ADDR_PRES, allowed),
+ MKT(UNI_ADDR_RESTRICT, restricted),
+ MKT(UNI_ADDR_NONUMBER, no-number),
+ EOT()
+};
+
+
+static void
+print_addr(struct unicx *cx, struct uni_addr *addr)
+{
+ static const struct uni_print_tbl plan_tbl[] = {
+ MKT(UNI_ADDR_UNKNOWN, unknown),
+ MKT(UNI_ADDR_E164, E164),
+ MKT(UNI_ADDR_ATME, ATME),
+ MKT(UNI_ADDR_DATA, data),
+ MKT(UNI_ADDR_PRIVATE, private),
+ EOT()
+ };
+ static const struct uni_print_tbl type_tbl[] = {
+ MKT(UNI_ADDR_UNKNOWN, unknown),
+ MKT(UNI_ADDR_INTERNATIONAL, international),
+ MKT(UNI_ADDR_NATIONAL, national),
+ MKT(UNI_ADDR_NETWORK, network),
+ MKT(UNI_ADDR_SUBSCR, subscriber),
+ MKT(UNI_ADDR_ABBR, abbreviated),
+ EOT()
+ };
+ u_int i;
+
+ uni_print_entry(cx, "addr", "(");
+ uni_print_tbl(NULL, addr->type, type_tbl, cx);
+ uni_putc(',', cx);
+ uni_print_tbl(NULL, addr->plan, plan_tbl, cx);
+ uni_putc(',', cx);
+ if(addr->plan == UNI_ADDR_E164) {
+ uni_putc('"', cx);
+ for(i = 0; i < addr->len; i++) {
+ if(addr->addr[i] < ' ')
+ uni_printf(cx, "^%c", addr->addr[i] + '@');
+ else if(addr->addr[i] <= '~')
+ uni_putc(addr->addr[i], cx);
+ else
+ uni_printf(cx, "\\%03o", addr->addr[i]);
+ }
+ uni_putc('"', cx);
+
+ } else if(addr->plan == UNI_ADDR_ATME) {
+ for(i = 0; i < addr->len; i++)
+ uni_printf(cx, "%02x", addr->addr[i]);
+ }
+ uni_putc(')', cx);
+}
+
+static void
+print_addrsub(struct unicx *cx, struct uni_subaddr *addr)
+{
+ static const struct uni_print_tbl type_tbl[] = {
+ MKT(UNI_SUBADDR_NSAP, NSAP),
+ MKT(UNI_SUBADDR_ATME, ATME),
+ MKT(UNI_SUBADDR_USER, USER),
+ EOT()
+ };
+ u_int i;
+
+ uni_print_entry(cx, "addr", "(");
+ uni_print_tbl(NULL, addr->type, type_tbl, cx);
+ uni_putc(',', cx);
+
+ for(i = 0; i < addr->len; i++)
+ uni_printf(cx, "%02x", addr->addr[i]);
+
+ uni_putc(')', cx);
+}
+
+static int
+check_addr(struct uni_addr *addr)
+{
+ u_int i;
+
+ switch(addr->plan) {
+ default:
+ return -1;
+
+ case UNI_ADDR_E164:
+ if(addr->type != UNI_ADDR_INTERNATIONAL)
+ return -1;
+ if(addr->len > 15 || addr->len == 0)
+ return -1;
+ for(i = 0; i < addr->len; i++)
+ if(addr->addr[i] == 0 || (addr->addr[i] & 0x80))
+ return -1;
+ break;
+
+ case UNI_ADDR_ATME:
+ if(addr->type != UNI_ADDR_UNKNOWN)
+ return -1;
+ if(addr->len != 20)
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+static int
+check_subaddr(struct uni_subaddr *addr)
+{
+ switch(addr->type) {
+ default:
+ return -1;
+
+ case UNI_SUBADDR_NSAP:
+ if(addr->len != 20)
+ return -1;
+ break;
+
+ case UNI_SUBADDR_ATME:
+ if(addr->len > 20)
+ return -1;
+ break;
+ }
+ return 0;
+}
+
+static int
+check_screen(enum uni_addr_screen screen, enum uni_addr_pres pres)
+{
+ switch(pres) {
+ default:
+ return -1;
+
+ case UNI_ADDR_PRES:
+ case UNI_ADDR_RESTRICT:
+ case UNI_ADDR_NONUMBER:
+ break;
+ }
+ switch(screen) {
+ default:
+ return -1;
+
+ case UNI_ADDR_SCREEN_NOT:
+ case UNI_ADDR_SCREEN_PASSED:
+ case UNI_ADDR_SCREEN_FAILED:
+ case UNI_ADDR_SCREEN_NET:
+ break;
+ }
+
+ return 0;
+}
+
+static void
+encode_addr(struct uni_msg *msg, struct uni_addr *addr, u_int flag,
+ enum uni_addr_screen screen, enum uni_addr_pres pres, int err)
+{
+ u_char ext = err ? 0x00 : 0x80;
+
+ if (flag) {
+ APP_BYTE(msg, (addr->type << 4) | addr->plan);
+ APP_BYTE(msg, ext | (pres << 5) | (screen));
+ } else {
+ APP_BYTE(msg, ext | (addr->type << 4) | addr->plan);
+ }
+ APP_BUF(msg, addr->addr, addr->len);
+}
+
+static void
+encode_subaddr(struct uni_msg *msg, struct uni_subaddr *addr)
+{
+ APP_BYTE(msg, 0x80|(addr->type<<4));
+ APP_BUF(msg, addr->addr, addr->len);
+}
+
+static int
+decode_addr(struct uni_addr *addr, u_int ielen, struct uni_msg *msg, u_int plan)
+{
+ addr->plan = plan & 0xf;
+ addr->type = (plan >> 4) & 0x7;
+
+ switch(addr->plan) {
+
+ case UNI_ADDR_E164:
+ if(ielen > 15 || ielen == 0)
+ return -1;
+ addr->addr[ielen] = 0;
+ break;
+
+ case UNI_ADDR_ATME:
+ if(ielen != 20)
+ return -1;
+ break;
+
+ default:
+ return -1;
+ }
+ (void)memcpy(addr->addr, msg->b_rptr, ielen);
+ addr->len = ielen;
+ msg->b_rptr += ielen;
+
+ return 0;
+}
+
+static int
+decode_subaddr(struct uni_subaddr *addr, u_int ielen, struct uni_msg *msg,
+ u_int type)
+{
+ switch(addr->type = (type >> 4) & 0x7) {
+
+ case UNI_SUBADDR_NSAP:
+ if(ielen == 0 || ielen > 20)
+ return -1;
+ break;
+
+ case UNI_SUBADDR_ATME:
+ if(ielen != 20)
+ return -1;
+ break;
+
+ default:
+ return -1;
+ }
+ if(!(type & 0x80))
+ return -1;
+ if((type & 0x7) != 0)
+ return -1;
+
+ addr->len = ielen;
+ (void)memcpy(addr->addr, msg->b_rptr, ielen);
+ msg->b_rptr += ielen;
+
+ return 0;
+}
+
+/**********************************************************************/
+
+DEF_IE_PRINT(itu, called)
+{
+ if (uni_print_iehdr("called", &ie->h, cx))
+ return;
+ print_addr(cx, &ie->addr);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, called)
+{
+ UNUSED(cx);
+
+ if (check_addr(&ie->addr))
+ return (-1);
+ return (0);
+}
+
+DEF_IE_ENCODE(itu, called)
+{
+ START_IE(called, UNI_IE_CALLED, 21);
+ encode_addr(msg, &ie->addr, 0, 0, 0, IE_ISERROR(*ie));
+ SET_IE_LEN(msg);
+ return (0);
+}
+
+DEF_IE_DECODE(itu, called)
+{
+ u_char c;
+ IE_START(;);
+
+ if (ielen > 21 || ielen < 1)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ ielen--;
+
+ if (!(c & 0x80))
+ goto rej;
+
+ if (decode_addr(&ie->addr, ielen, msg, c))
+ goto rej;
+
+ IE_END(CALLED);
+}
+
+/**********************************************************************/
+
+DEF_IE_PRINT(itu, calledsub)
+{
+ if(uni_print_iehdr("calledsub", &ie->h, cx))
+ return;
+ print_addrsub(cx, &ie->addr);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, calledsub)
+{
+ UNUSED(cx);
+
+ if(check_subaddr(&ie->addr))
+ return -1;
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, calledsub)
+{
+ START_IE(calledsub, UNI_IE_CALLEDSUB, 21);
+ encode_subaddr(msg, &ie->addr);
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, calledsub)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen > 21)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ ielen--;
+
+ if(decode_subaddr(&ie->addr, ielen, msg, c))
+ goto rej;
+
+ IE_END(CALLEDSUB);
+}
+
+/**********************************************************************/
+
+DEF_IE_PRINT(itu, calling)
+{
+ if(uni_print_iehdr("calling", &ie->h, cx))
+ return;
+ print_addr(cx, &ie->addr);
+
+ if(ie->h.present & UNI_CALLING_SCREEN_P) {
+ uni_print_tbl("screening", ie->screen, screen_tbl, cx);
+ uni_print_tbl("presentation", ie->pres, pres_tbl, cx);
+ }
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, calling)
+{
+ UNUSED(cx);
+
+ if(check_addr(&ie->addr))
+ return -1;
+
+ if(ie->h.present & UNI_CALLING_SCREEN_P)
+ if(check_screen(ie->screen, ie->pres))
+ return -1;
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, calling)
+{
+ START_IE(calling, UNI_IE_CALLING, 22);
+ encode_addr(msg, &ie->addr, ie->h.present & UNI_CALLING_SCREEN_P, ie->screen, ie->pres, IE_ISERROR(*ie));
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, calling)
+{
+ u_char c, plan;
+
+ IE_START(;);
+
+ if(ielen > 22 || ielen < 1)
+ goto rej;
+
+ plan = *msg->b_rptr++;
+ ielen--;
+
+ if(!(plan & 0x80)) {
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+
+ ie->h.present |= UNI_CALLING_SCREEN_P;
+ ie->pres = (c >> 5) & 0x3;
+ ie->screen = c & 0x3;
+
+ if(!(c & 0x80))
+ goto rej;
+ }
+
+ if(decode_addr(&ie->addr, ielen, msg, plan))
+ goto rej;
+
+ IE_END(CALLING);
+}
+
+/**********************************************************************/
+
+DEF_IE_PRINT(itu, callingsub)
+{
+ if(uni_print_iehdr("callingsub", &ie->h, cx))
+ return;
+ print_addrsub(cx, &ie->addr);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, callingsub)
+{
+ UNUSED(cx);
+
+ if(check_subaddr(&ie->addr))
+ return -1;
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, callingsub)
+{
+ START_IE(callingsub, UNI_IE_CALLINGSUB, 21);
+ encode_subaddr(msg, &ie->addr);
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, callingsub)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen > 21)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ ielen--;
+
+ if(decode_subaddr(&ie->addr, ielen, msg, c))
+ goto rej;
+
+ IE_END(CALLINGSUB);
+}
+
+/**********************************************************************/
+
+DEF_IE_PRINT(itu, conned)
+{
+ if(uni_print_iehdr("conned", &ie->h, cx))
+ return;
+ print_addr(cx, &ie->addr);
+
+ if(ie->h.present & UNI_CONNED_SCREEN_P) {
+ uni_print_tbl("screening", ie->screen, screen_tbl, cx);
+ uni_print_tbl("presentation", ie->pres, pres_tbl, cx);
+ }
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, conned)
+{
+ UNUSED(cx);
+
+ if(check_addr(&ie->addr))
+ return -1;
+
+ if(ie->h.present & UNI_CONNED_SCREEN_P)
+ if(check_screen(ie->screen, ie->pres))
+ return -1;
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, conned)
+{
+ START_IE(conned, UNI_IE_CONNED, 22);
+ encode_addr(msg, &ie->addr, ie->h.present & UNI_CONNED_SCREEN_P, ie->screen, ie->pres, IE_ISERROR(*ie));
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, conned)
+{
+ u_char c, plan;
+
+ IE_START(;);
+
+ if(ielen > 22 || ielen < 1)
+ goto rej;
+
+ plan = *msg->b_rptr++;
+ ielen--;
+
+ if(!(plan & 0x80)) {
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+
+ ie->h.present |= UNI_CONNED_SCREEN_P;
+ ie->pres = (c >> 5) & 0x3;
+ ie->screen = c & 0x3;
+
+ if(!(c & 0x80))
+ goto rej;
+ }
+
+ if(decode_addr(&ie->addr, ielen, msg, plan))
+ goto rej;
+
+ IE_END(CONNED);
+}
+
+/**********************************************************************/
+
+DEF_IE_PRINT(itu, connedsub)
+{
+ if(uni_print_iehdr("connedsub", &ie->h, cx))
+ return;
+ print_addrsub(cx, &ie->addr);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, connedsub)
+{
+ UNUSED(cx);
+
+ if(check_subaddr(&ie->addr))
+ return -1;
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, connedsub)
+{
+ START_IE(connedsub, UNI_IE_CONNEDSUB, 21);
+ encode_subaddr(msg, &ie->addr);
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, connedsub)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen > 21)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ ielen--;
+
+ if(decode_subaddr(&ie->addr, ielen, msg, c))
+ goto rej;
+
+ IE_END(CONNEDSUB);
+}
+
+/*********************************************************************
+ *
+ * Endpoint reference.
+ *
+ * References for this IE are:
+ *
+ * Q.2971 p. 14
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, epref)
+{
+ if(uni_print_iehdr("epref", &ie->h, cx))
+ return;
+ uni_print_entry(cx, "epref", "(%u,%u)", ie->flag, ie->epref);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, epref)
+{
+ UNUSED(cx);
+
+ if(ie->epref >= (2<<15))
+ return -1;
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, epref)
+{
+ START_IE(epref, UNI_IE_EPREF, 3);
+
+ if (IE_ISERROR(*ie))
+ APP_BYTE(msg, 0xff);
+ else
+ APP_BYTE(msg, 0);
+ APP_BYTE(msg, (ie->flag << 7) | ((ie->epref >> 8) & 0x7f));
+ APP_BYTE(msg, (ie->epref & 0xff));
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, epref)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen != 3)
+ goto rej;
+ if(*msg->b_rptr++ != 0)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ ie->flag = (c & 0x80) ? 1 : 0;
+ ie->epref = (c & 0x7f) << 8;
+ ie->epref |= *msg->b_rptr++;
+
+ IE_END(EPREF);
+}
+
+/*********************************************************************
+ *
+ * Endpoint state.
+ *
+ * References for this IE are:
+ *
+ * Q.2971 pp. 14...15
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, epstate)
+{
+ static const struct uni_print_tbl tbl[] = {
+ MKT(UNI_EPSTATE_NULL, null),
+ MKT(UNI_EPSTATE_ADD_INIT, add-initiated),
+ MKT(UNI_EPSTATE_ALERT_DLVD, alerting-delivered),
+ MKT(UNI_EPSTATE_ADD_RCVD, add-received),
+ MKT(UNI_EPSTATE_ALERT_RCVD, alerting-received),
+ MKT(UNI_EPSTATE_ACTIVE, active),
+ MKT(UNI_EPSTATE_DROP_INIT, drop-initiated),
+ MKT(UNI_EPSTATE_DROP_RCVD, drop-received),
+ EOT()
+ };
+
+ if(uni_print_iehdr("epstate", &ie->h, cx))
+ return;
+ uni_print_tbl("state", ie->state, tbl, cx);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, epstate)
+{
+ UNUSED(cx);
+
+ switch(ie->state) {
+ default:
+ return -1;
+
+ case UNI_EPSTATE_NULL:
+ case UNI_EPSTATE_ADD_INIT:
+ case UNI_EPSTATE_ALERT_DLVD:
+ case UNI_EPSTATE_ADD_RCVD:
+ case UNI_EPSTATE_ALERT_RCVD:
+ case UNI_EPSTATE_DROP_INIT:
+ case UNI_EPSTATE_DROP_RCVD:
+ case UNI_EPSTATE_ACTIVE:
+ break;
+ }
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, epstate)
+{
+ START_IE(epstate, UNI_IE_EPSTATE, 1);
+
+ APP_BYTE(msg, ie->state);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, epstate)
+{
+ IE_START(;);
+
+ if(ielen != 1)
+ goto rej;
+
+ ie->state = *msg->b_rptr++ & 0x3f;
+
+ IE_END(EPSTATE);
+}
+
+/*********************************************************************
+ *
+ * ATM adaptation layer parameters
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 43...49
+ * Q.2931 Amd 2
+ * UNI4.0 p. 9
+ *
+ * UNI4.0 states, that AAL2 is not supported. However we keep it. No
+ * parameters are associated with AAL2.
+ *
+ * Amd2 not checked. XXX
+ *
+ * Only ITU-T coding allowed.
+ */
+DEF_IE_PRINT(itu, aal)
+{
+ static const struct uni_print_tbl aal_tbl[] = {
+ MKT(UNI_AAL_0, VOICE),
+ MKT(UNI_AAL_1, 1),
+ MKT(UNI_AAL_2, 2),
+ MKT(UNI_AAL_4, 3/4),
+ MKT(UNI_AAL_5, 5),
+ MKT(UNI_AAL_USER, USER),
+ EOT()
+ };
+ static const struct uni_print_tbl subtype_tbl[] = {
+ MKT(UNI_AAL1_SUB_NULL, null),
+ MKT(UNI_AAL1_SUB_VOICE, voice),
+ MKT(UNI_AAL1_SUB_CIRCUIT, circuit),
+ MKT(UNI_AAL1_SUB_HQAUDIO, hqaudio),
+ MKT(UNI_AAL1_SUB_VIDEO, video),
+ EOT()
+ };
+ static const struct uni_print_tbl cbr_rate_tbl[] = {
+ MKT(UNI_AAL1_CBR_64, 64),
+ MKT(UNI_AAL1_CBR_1544, 1544(DS1)),
+ MKT(UNI_AAL1_CBR_6312, 6312(DS2)),
+ MKT(UNI_AAL1_CBR_32064, 32064),
+ MKT(UNI_AAL1_CBR_44736, 44736(DS3)),
+ MKT(UNI_AAL1_CBR_97728, 97728),
+ MKT(UNI_AAL1_CBR_2048, 2048(E1)),
+ MKT(UNI_AAL1_CBR_8448, 8448(E2)),
+ MKT(UNI_AAL1_CBR_34368, 34368(E3)),
+ MKT(UNI_AAL1_CBR_139264, 139264),
+ MKT(UNI_AAL1_CBR_N64, Nx64),
+ MKT(UNI_AAL1_CBR_N8, Nx8),
+ EOT()
+ };
+ static const struct uni_print_tbl screc_tbl[] = {
+ MKT(UNI_AAL1_SCREC_NULL, null),
+ MKT(UNI_AAL1_SCREC_SRTS, srts),
+ MKT(UNI_AAL1_SCREC_ACLK, aclk),
+ EOT()
+ };
+ static const struct uni_print_tbl ecm_tbl[] = {
+ MKT(UNI_AAL1_ECM_NULL, null),
+ MKT(UNI_AAL1_ECM_LOSS, loss),
+ MKT(UNI_AAL1_ECM_DELAY, delay),
+ EOT()
+ };
+ static const struct uni_print_tbl sscs_tbl[] = {
+ MKT(UNI_AAL_SSCS_NULL, null),
+ MKT(UNI_AAL_SSCS_SSCOPA, sscopa),
+ MKT(UNI_AAL_SSCS_SSCOPU, sscopu),
+ MKT(UNI_AAL_SSCS_FRAME, frame),
+ EOT()
+ };
+
+ if(uni_print_iehdr("aal", &ie->h, cx))
+ return;
+ uni_print_tbl("type", ie->type, aal_tbl, cx);
+
+ switch(ie->type) {
+
+ case UNI_AAL_0:
+ uni_print_push_prefix("0", cx);
+ cx->indent++;
+ break;
+
+ case UNI_AAL_2:
+ uni_print_push_prefix("2", cx);
+ cx->indent++;
+ break;
+
+ case UNI_AAL_1:
+ uni_print_push_prefix("1", cx);
+ cx->indent++;
+ uni_print_tbl("subtype", ie->u.aal1.subtype, subtype_tbl, cx);
+ uni_print_tbl("cbr_rate", ie->u.aal1.cbr_rate, cbr_rate_tbl, cx);
+ if(ie->h.present & UNI_AAL1_MULT_P)
+ uni_print_entry(cx, "mult", "%u", ie->u.aal1.mult);
+ if(ie->h.present & UNI_AAL1_SCREC_P)
+ uni_print_tbl("screc", ie->u.aal1.screc, screc_tbl, cx);
+ if(ie->h.present & UNI_AAL1_ECM_P)
+ uni_print_tbl("ecm", ie->u.aal1.ecm, ecm_tbl, cx);
+ if(ie->h.present & UNI_AAL1_BSIZE_P)
+ uni_print_entry(cx, "bsize", "%u", ie->u.aal1.bsize);
+ if(ie->h.present & UNI_AAL1_PART_P)
+ uni_print_entry(cx, "part", "%u", ie->u.aal1.part);
+ break;
+
+ case UNI_AAL_4:
+ uni_print_push_prefix("4", cx);
+ cx->indent++;
+ if(ie->h.present & UNI_AAL4_CPCS_P)
+ uni_print_entry(cx, "cpcs", "(%u,%u)", ie->u.aal4.fwd_cpcs,
+ ie->u.aal4.bwd_cpcs);
+ if(ie->h.present & UNI_AAL4_MID_P)
+ uni_print_entry(cx, "mid", "(%u,%u)", ie->u.aal4.mid_low,
+ ie->u.aal4.mid_high);
+ if(ie->h.present & UNI_AAL4_SSCS_P)
+ uni_print_tbl("sscs", ie->u.aal4.sscs, sscs_tbl, cx);
+ break;
+
+ case UNI_AAL_5:
+ uni_print_push_prefix("5", cx);
+ cx->indent++;
+ if(ie->h.present & UNI_AAL5_CPCS_P)
+ uni_print_entry(cx, "cpcs", "(%u,%u)", ie->u.aal5.fwd_cpcs,
+ ie->u.aal5.bwd_cpcs);
+ if(ie->h.present & UNI_AAL5_SSCS_P)
+ uni_print_tbl("sscs", ie->u.aal5.sscs, sscs_tbl, cx);
+ break;
+
+ case UNI_AAL_USER:
+ uni_print_push_prefix("user", cx);
+ cx->indent++;
+ if(ie->u.aalu.len > 4) {
+ uni_print_entry(cx, "info", "ERROR(len=%u)", ie->u.aalu.len);
+ } else {
+ u_int i;
+
+ uni_print_entry(cx, "info", "(");
+ for(i = 0; i < ie->u.aalu.len; i++)
+ uni_printf(cx, "%s%u", !i?"":",", ie->u.aalu.user[i]);
+ uni_printf(cx, ")");
+ }
+ break;
+ }
+ cx->indent--;
+ uni_print_pop_prefix(cx);
+ uni_print_eol(cx);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, aal)
+{
+ UNUSED(cx);
+
+ if(ie->type == UNI_AAL_0) {
+ ;
+ } else if(ie->type == UNI_AAL_1) {
+ switch(ie->u.aal1.subtype) {
+
+ default:
+ return -1;
+
+ case UNI_AAL1_SUB_NULL:
+ case UNI_AAL1_SUB_VOICE:
+ case UNI_AAL1_SUB_CIRCUIT:
+ case UNI_AAL1_SUB_HQAUDIO:
+ case UNI_AAL1_SUB_VIDEO:
+ break;
+ }
+ switch(ie->u.aal1.cbr_rate) {
+
+ default:
+ return -1;
+
+ case UNI_AAL1_CBR_64:
+ case UNI_AAL1_CBR_1544:
+ case UNI_AAL1_CBR_6312:
+ case UNI_AAL1_CBR_32064:
+ case UNI_AAL1_CBR_44736:
+ case UNI_AAL1_CBR_97728:
+ case UNI_AAL1_CBR_2048:
+ case UNI_AAL1_CBR_8448:
+ case UNI_AAL1_CBR_34368:
+ case UNI_AAL1_CBR_139264:
+ if((ie->h.present & UNI_AAL1_MULT_P))
+ return -1;
+ break;
+
+ case UNI_AAL1_CBR_N64:
+ if(!(ie->h.present & UNI_AAL1_MULT_P))
+ return -1;
+ if(ie->u.aal1.mult < 2)
+ return -1;
+ break;
+
+ case UNI_AAL1_CBR_N8:
+ if(!(ie->h.present & UNI_AAL1_MULT_P))
+ return -1;
+ if(ie->u.aal1.mult == 0 || ie->u.aal1.mult > 7)
+ return -1;
+ break;
+ }
+ if(ie->h.present & UNI_AAL1_SCREC_P) {
+ switch(ie->u.aal1.screc) {
+
+ default:
+ return -1;
+
+ case UNI_AAL1_SCREC_NULL:
+ case UNI_AAL1_SCREC_SRTS:
+ case UNI_AAL1_SCREC_ACLK:
+ break;
+ }
+ }
+ if(ie->h.present & UNI_AAL1_ECM_P) {
+ switch(ie->u.aal1.ecm) {
+
+ default:
+ return -1;
+
+ case UNI_AAL1_ECM_NULL:
+ case UNI_AAL1_ECM_LOSS:
+ case UNI_AAL1_ECM_DELAY:
+ break;
+ }
+ }
+ if(ie->h.present & UNI_AAL1_BSIZE_P) {
+ if(ie->u.aal1.bsize == 0)
+ return -1;
+ }
+ if(ie->h.present & UNI_AAL1_PART_P) {
+ if(ie->u.aal1.part == 0 || ie->u.aal1.part > 47)
+ return -1;
+ }
+
+ } else if(ie->type == UNI_AAL_2) {
+ ;
+
+ } else if(ie->type == UNI_AAL_4) {
+ if(ie->h.present & UNI_AAL4_MID_P) {
+ if(ie->u.aal4.mid_low >= 1024)
+ return -1;
+ if(ie->u.aal4.mid_high >= 1024)
+ return -1;
+ if(ie->u.aal4.mid_low > ie->u.aal4.mid_high)
+ return -1;
+ }
+ if(ie->h.present & UNI_AAL4_SSCS_P) {
+ switch(ie->u.aal4.sscs) {
+
+ default:
+ return -1;
+
+ case UNI_AAL_SSCS_NULL:
+ case UNI_AAL_SSCS_SSCOPA:
+ case UNI_AAL_SSCS_SSCOPU:
+ case UNI_AAL_SSCS_FRAME:
+ break;
+ }
+ }
+
+ } else if(ie->type == UNI_AAL_5) {
+ if(ie->h.present & UNI_AAL5_SSCS_P) {
+ switch(ie->u.aal5.sscs) {
+
+ default:
+ return -1;
+
+ case UNI_AAL_SSCS_NULL:
+ case UNI_AAL_SSCS_SSCOPA:
+ case UNI_AAL_SSCS_SSCOPU:
+ case UNI_AAL_SSCS_FRAME:
+ break;
+ }
+ }
+
+ } else if(ie->type == UNI_AAL_USER) {
+ if(ie->u.aalu.len > 4)
+ return -1;
+
+ } else
+ return -1;
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, aal)
+{
+ START_IE(aal, UNI_IE_AAL, 16);
+
+ APP_BYTE(msg, ie->type);
+ switch(ie->type) {
+
+ case UNI_AAL_0:
+ break;
+
+ case UNI_AAL_1:
+ APP_SUB_BYTE(msg,
+ UNI_AAL_SUB_ID, ie->u.aal1.subtype);
+ APP_SUB_BYTE(msg,
+ UNI_AAL_CBR_ID, ie->u.aal1.cbr_rate);
+ APP_OPT_16BIT(msg, ie->h.present, UNI_AAL1_MULT_P,
+ UNI_AAL_MULT_ID, ie->u.aal1.mult);
+ APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_SCREC_P,
+ UNI_AAL_SCREC_ID, ie->u.aal1.screc);
+ APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_ECM_P,
+ UNI_AAL_ECM_ID, ie->u.aal1.ecm);
+ APP_OPT_16BIT(msg, ie->h.present, UNI_AAL1_BSIZE_P,
+ UNI_AAL_BSIZE_ID, ie->u.aal1.bsize);
+ APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_PART_P,
+ UNI_AAL_PART_ID, ie->u.aal1.part);
+ break;
+
+ case UNI_AAL_2:
+ break;
+
+ case UNI_AAL_4:
+ if(ie->h.present & UNI_AAL4_CPCS_P) {
+ APP_SUB_16BIT(msg,
+ UNI_AAL_FWDCPCS_ID, ie->u.aal4.fwd_cpcs);
+ APP_SUB_16BIT(msg,
+ UNI_AAL_BWDCPCS_ID, ie->u.aal4.bwd_cpcs);
+ }
+ if(ie->h.present & UNI_AAL4_MID_P) {
+ APP_BYTE(msg, UNI_AAL_MID_ID);
+ APP_16BIT(msg, ie->u.aal4.mid_low);
+ APP_16BIT(msg, ie->u.aal4.mid_high);
+ }
+ APP_OPT_BYTE(msg, ie->h.present, UNI_AAL4_SSCS_P,
+ UNI_AAL_SSCS_ID, ie->u.aal4.sscs);
+ break;
+
+ case UNI_AAL_5:
+ if(ie->h.present & UNI_AAL5_CPCS_P) {
+ APP_SUB_16BIT(msg,
+ UNI_AAL_FWDCPCS_ID, ie->u.aal5.fwd_cpcs);
+ APP_SUB_16BIT(msg,
+ UNI_AAL_BWDCPCS_ID, ie->u.aal5.bwd_cpcs);
+ }
+ APP_OPT_BYTE(msg, ie->h.present, UNI_AAL5_SSCS_P,
+ UNI_AAL_SSCS_ID, ie->u.aal5.sscs);
+ break;
+
+ case UNI_AAL_USER:
+ APP_BUF(msg, ie->u.aalu.user, ie->u.aalu.len);
+ break;
+
+ default:
+ return -1;
+ }
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+/*
+ * XXX What should we do with multiple subtype occurences? Ignore
+ * or reject. Currently we reject.
+ */
+static int
+decode_aal_1(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
+{
+ int subtype_p, cbr_p;
+
+ subtype_p = cbr_p = 0;
+
+ while(ielen-- > 0) {
+ switch(*msg->b_rptr++) {
+
+ case UNI_AAL_SUB_ID:
+ if(ielen == 0 || subtype_p)
+ return -1;
+ ielen--;
+ subtype_p = 1;
+ ie->u.aal1.subtype = *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_CBR_ID:
+ if(ielen == 0 || cbr_p)
+ return -1;
+ ielen--;
+ cbr_p = 1;
+ ie->u.aal1.cbr_rate = *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_MULT_ID:
+ if(ielen < 2 || (ie->h.present & UNI_AAL1_MULT_P))
+ return -1;
+ ielen -= 2;
+ ie->h.present |= UNI_AAL1_MULT_P;
+ ie->u.aal1.mult = *msg->b_rptr++ << 8;
+ ie->u.aal1.mult |= *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_SCREC_ID:
+ if(ielen == 0 || (ie->h.present & UNI_AAL1_SCREC_P))
+ return -1;
+ ielen--;
+ ie->h.present |= UNI_AAL1_SCREC_P;
+ ie->u.aal1.screc = *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_ECM_ID:
+ if(ielen == 0 || (ie->h.present & UNI_AAL1_ECM_P))
+ return -1;
+ ielen--;
+ ie->h.present |= UNI_AAL1_ECM_P;
+ ie->u.aal1.ecm = *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_BSIZE_ID:
+ if(ielen < 2 || (ie->h.present & UNI_AAL1_BSIZE_P))
+ return -1;
+ ielen -= 2;
+ ie->h.present |= UNI_AAL1_BSIZE_P;
+ ie->u.aal1.bsize = *msg->b_rptr++ << 8;
+ ie->u.aal1.bsize |= *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_PART_ID:
+ if(ielen == 0 || (ie->h.present & UNI_AAL1_PART_P))
+ return -1;
+ ielen--;
+ ie->h.present |= UNI_AAL1_PART_P;
+ ie->u.aal1.part = *msg->b_rptr++;
+ break;
+
+ default:
+ return -1;
+ }
+ }
+ if(!subtype_p || !cbr_p)
+ return -1;
+
+ return 0;
+}
+
+static int
+decode_aal_4(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
+{
+ int fcpcs_p, bcpcs_p;
+
+ fcpcs_p = bcpcs_p = 0;
+
+ while(ielen-- > 0) {
+ switch(*msg->b_rptr++) {
+
+ case UNI_AAL_FWDCPCS_ID:
+ if(ielen < 2 || fcpcs_p)
+ return -1;
+ ielen -= 2;
+ fcpcs_p = 1;
+ ie->u.aal4.fwd_cpcs = *msg->b_rptr++ << 8;
+ ie->u.aal4.fwd_cpcs |= *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_BWDCPCS_ID:
+ if(ielen < 2 || bcpcs_p)
+ return -1;
+ ielen -= 2;
+ bcpcs_p = 1;
+ ie->u.aal4.bwd_cpcs = *msg->b_rptr++ << 8;
+ ie->u.aal4.bwd_cpcs |= *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_MID_ID:
+ if(ielen < 4 || (ie->h.present & UNI_AAL4_MID_P))
+ return -1;
+ ielen -= 4;
+ ie->h.present |= UNI_AAL4_MID_P;
+ ie->u.aal4.mid_low = *msg->b_rptr++ << 8;
+ ie->u.aal4.mid_low |= *msg->b_rptr++;
+ ie->u.aal4.mid_high = *msg->b_rptr++ << 8;
+ ie->u.aal4.mid_high |= *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_SSCS_ID:
+ if(ielen == 0 || (ie->h.present & UNI_AAL4_SSCS_P))
+ return -1;
+ ielen--;
+ ie->h.present |= UNI_AAL4_SSCS_P;
+ ie->u.aal4.sscs = *msg->b_rptr++;
+ break;
+
+ default:
+ return -1;
+ }
+ }
+
+ if(fcpcs_p ^ bcpcs_p)
+ return -1;
+ if(fcpcs_p)
+ ie->h.present |= UNI_AAL4_CPCS_P;
+
+ return 0;
+}
+
+static int
+decode_aal_5(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
+{
+ int fcpcs_p, bcpcs_p;
+
+ fcpcs_p = bcpcs_p = 0;
+
+ while(ielen-- > 0) {
+ switch(*msg->b_rptr++) {
+
+ case UNI_AAL_FWDCPCS_ID:
+ if(ielen < 2 || fcpcs_p)
+ return -1;
+ ielen -= 2;
+ fcpcs_p = 1;
+ ie->u.aal5.fwd_cpcs = *msg->b_rptr++ << 8;
+ ie->u.aal5.fwd_cpcs |= *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_BWDCPCS_ID:
+ if(ielen < 2 || bcpcs_p)
+ return -1;
+ ielen -= 2;
+ bcpcs_p = 1;
+ ie->u.aal5.bwd_cpcs = *msg->b_rptr++ << 8;
+ ie->u.aal5.bwd_cpcs |= *msg->b_rptr++;
+ break;
+
+ case UNI_AAL_SSCS_ID:
+ if(ielen == 0 || (ie->h.present & UNI_AAL5_SSCS_P))
+ return -1;
+ ielen--;
+ ie->h.present |= UNI_AAL5_SSCS_P;
+ ie->u.aal5.sscs = *msg->b_rptr++;
+ break;
+
+ default:
+ return -1;
+ }
+ }
+
+ if(fcpcs_p ^ bcpcs_p)
+ return -1;
+ if(fcpcs_p)
+ ie->h.present |= UNI_AAL5_CPCS_P;
+
+ return 0;
+}
+
+static int
+decode_aal_user(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
+{
+ if(ielen > 4)
+ return -1;
+
+ ie->u.aalu.len = 0;
+ while(ielen--)
+ ie->u.aalu.user[ie->u.aalu.len++] = *msg->b_rptr++;
+
+ return 0;
+}
+
+DEF_IE_DECODE(itu, aal)
+{
+ u_char c;
+
+ IE_START(DISC_ACC_ERR(AAL));
+
+ if(ielen < 1 || ielen > 21)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ ielen--;
+
+ switch(c) {
+
+ case UNI_AAL_0:
+ ie->type = c;
+ break;
+
+ case UNI_AAL_1:
+ ie->type = c;
+ if(decode_aal_1(ie, msg, ielen))
+ goto rej;
+ break;
+
+ case UNI_AAL_2:
+ ie->type = c;
+ break;
+
+ case UNI_AAL_4:
+ ie->type = c;
+ if(decode_aal_4(ie, msg, ielen))
+ goto rej;
+ break;
+
+ case UNI_AAL_5:
+ ie->type = c;
+ if(decode_aal_5(ie, msg, ielen))
+ goto rej;
+ break;
+
+ case UNI_AAL_USER:
+ ie->type = c;
+ if(decode_aal_user(ie, msg, ielen))
+ goto rej;
+ break;
+
+ default:
+ goto rej;
+ }
+
+ IE_END(AAL);
+}
+
+/*********************************************************************
+ *
+ * Traffic descriptor.
+ * Alternate traffic descriptor.
+ * Minimum traffic descriptor.
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 49...51
+ * Q.2961
+ * Q.2962
+ * UNI4.0 pp. 9...10, 106...109
+ *
+ * The Q.s specify the coding. UNI4.0 adds frame discard and best-effort.
+ * Appendix in UNI4.0 lists the allowed combinations.
+ *
+ * PCR0 PCR1 SCR/MBS0 SCR/MBS1 BE TAG FDISC ABR
+ * 1 CBR.1 - Y - - - N Y/N -
+ * 2 CBR.2 - Y - - - N Y/N - (*)
+ * 3 CBR.3 Y Y - - - Y Y/N - (*)
+ * 4 rt-VBR.1 - Y - Y - N Y/N -
+ * 5 rt-VBR.2 - Y Y - - N Y/N -
+ * 6 rt-VBR.3 - Y Y - - Y Y/N -
+ * 7 rt-VBR.4 Y Y - - - Y/N Y/N - (*)
+ * 8 rt-VBR.5 - Y - - - N Y/N - (*)
+ * 9 rt-VBR.6 - Y - Y - N Y/N - (*)
+ * 10 nrt-VBR.1 - Y - Y - N Y/N -
+ * 11 nrt-VBR.2 - Y Y - - N Y/N -
+ * 12 nrt-VBR.3 - Y Y - - Y Y/N -
+ * 13 nrt-VBR.4 Y Y - - - Y/N Y/N - (*)
+ * 14 nrt-VBR.5 - Y - - - N Y/N - (*)
+ * 15 nrt-VBR.6 - Y - Y - N Y/N - (*)
+ * 16 ABR - Y - - - N Y/N O (*)
+ * 17 UBR.1 - Y - - Y N Y/N -
+ * 18 UBR.2 - Y - - Y Y Y/N -
+ *
+ * Allow ITU-T and NET coding, because its not clear, whether the
+ * new fields in UNI4.0 should be used with NET coding or not.
+ * Does not allow for experimental codings yet.
+ */
+
+static void
+print_ie_traffic_common(struct unicx *cx, u_int present, struct uni_xtraffic *ie)
+{
+ uni_print_entry(cx, "fwd", "(");
+ if(present & UNI_TRAFFIC_FPCR0_P)
+ uni_printf(cx, "%u", ie->fpcr0);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_FPCR1_P)
+ uni_printf(cx, "%u", ie->fpcr1);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_FSCR0_P)
+ uni_printf(cx, "%u", ie->fscr0);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_FSCR1_P)
+ uni_printf(cx, "%u", ie->fscr1);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_FMBS0_P)
+ uni_printf(cx, "%u", ie->fmbs0);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_FMBS1_P)
+ uni_printf(cx, "%u", ie->fmbs1);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_FABR1_P)
+ uni_printf(cx, "%u", ie->fabr1);
+ uni_printf(cx, ")");
+
+ uni_print_entry(cx, "bwd", "(");
+ if(present & UNI_TRAFFIC_BPCR0_P)
+ uni_printf(cx, "%u", ie->bpcr0);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_BPCR1_P)
+ uni_printf(cx, "%u", ie->bpcr1);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_BSCR0_P)
+ uni_printf(cx, "%u", ie->bscr0);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_BSCR1_P)
+ uni_printf(cx, "%u", ie->bscr1);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_BMBS0_P)
+ uni_printf(cx, "%u", ie->bmbs0);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_BMBS1_P)
+ uni_printf(cx, "%u", ie->bmbs1);
+ uni_putc(',', cx);
+ if(present & UNI_TRAFFIC_BABR1_P)
+ uni_printf(cx, "%u", ie->babr1);
+ uni_printf(cx, ")");
+
+ if(present & UNI_TRAFFIC_BEST_P)
+ uni_print_flag("best_effort", cx);
+ if(present & UNI_TRAFFIC_MOPT_P) {
+ uni_print_entry(cx, "tag", "(");
+ if(ie->ftag)
+ uni_printf(cx, "fwd");
+ uni_putc(',', cx);
+ if(ie->btag)
+ uni_printf(cx, "bwd");
+ uni_putc(')', cx);
+
+ uni_print_entry(cx, "disc", "(");
+ if(ie->fdisc)
+ uni_printf(cx, "fwd");
+ uni_putc(',', cx);
+ if(ie->bdisc)
+ uni_printf(cx, "bwd");
+ uni_putc(')', cx);
+ }
+}
+
+struct tallow {
+ u_int mask;
+ int mopt_flag;
+ u_char mopt_mask, mopt_val;
+};
+
+static int
+check_traffic(u_int mask, u_int mopt, struct tallow *a)
+{
+ if(mask != a->mask)
+ return 0;
+
+ if(a->mopt_flag == 0) {
+ /* not allowed */
+ if(mopt == 0xffff)
+ return 1;
+ return 0;
+ }
+
+ if(a->mopt_flag < 0) {
+ /* optional */
+ if(mopt == 0xffff)
+ return 1;
+ if((mopt & a->mopt_mask) == a->mopt_val)
+ return 1;
+ return 0;
+ }
+
+ /* required */
+ if(mopt == 0xffff)
+ return 0;
+ if((mopt & a->mopt_mask) == a->mopt_val)
+ return 1;
+ return 0;
+}
+
+static int
+check_ie_traffic_common(struct uni_xtraffic *ie, u_int present,
+ struct unicx *cx __unused)
+{
+ static u_int fmask =
+ UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P |
+ UNI_TRAFFIC_FSCR0_P | UNI_TRAFFIC_FSCR1_P |
+ UNI_TRAFFIC_FMBS0_P | UNI_TRAFFIC_FMBS1_P |
+ UNI_TRAFFIC_FABR1_P;
+ static u_int bmask =
+ UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P |
+ UNI_TRAFFIC_BSCR0_P | UNI_TRAFFIC_BSCR1_P |
+ UNI_TRAFFIC_BMBS0_P | UNI_TRAFFIC_BMBS1_P |
+ UNI_TRAFFIC_BABR1_P;
+#define DTAB(U,X) \
+ { U##X##PCR1_P, \
+ -1, U##X##TAG, 0 }, /* 1, 2, 8, 14 */ \
+ { U##X##PCR0_P | U##X##PCR1_P, \
+ +1, U##X##TAG, U##X##TAG }, /* 3 */ \
+ { U##X##PCR1_P | U##X##SCR1_P | U##X##MBS1_P, \
+ -1, U##X##TAG, 0 }, /* 4, 9, 10, 15 */ \
+ { U##X##PCR1_P | U##X##SCR0_P | U##X##MBS0_P, \
+ -1, 0, 0 }, /* 5, 6, 11, 12 */ \
+ { U##X##PCR0_P | U##X##PCR1_P, \
+ -1, 0, 0 }, /* 7, 13 */ \
+ { U##X##PCR1_P | U##X##ABR1_P, \
+ -1, U##X##TAG, 0 }, /* 16a */
+#define DTABSIZE 6
+
+ static struct tallow allow[2][DTABSIZE] = {
+ { DTAB(UNI_TRAFFIC_, F) },
+ { DTAB(UNI_TRAFFIC_, B) },
+ };
+#undef DTAB
+
+ u_int f, b, p, m;
+ int i;
+
+ f = present & fmask;
+ b = present & bmask;
+ p = present & (fmask | bmask);
+ m = (present & UNI_TRAFFIC_MOPT_P)
+ ? ( (ie->ftag ? UNI_TRAFFIC_FTAG : 0)
+ | (ie->btag ? UNI_TRAFFIC_BTAG : 0)
+ | (ie->fdisc ? UNI_TRAFFIC_FDISC : 0)
+ | (ie->bdisc ? UNI_TRAFFIC_BDISC : 0))
+ : 0xffff;
+
+
+ if(present & UNI_TRAFFIC_BEST_P) {
+ /*
+ * Lines 17 and 18
+ */
+ if(p != (UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_BPCR1_P))
+ return -1;
+ return 0;
+ }
+
+ /*
+ * Check forward and backward independent. There must be a higher
+ * level checking in the CAC
+ */
+ for(i = 0; i < DTABSIZE; i++)
+ if(check_traffic(f, m, &allow[0][i]))
+ break;
+ if(i == DTABSIZE)
+ return -1;
+
+ for(i = 0; i < DTABSIZE; i++)
+ if(check_traffic(b, m, &allow[1][i]))
+ break;
+ if(i == DTABSIZE)
+ return -1;
+
+ return 0;
+}
+
+static int
+encode_traffic_common(struct uni_msg *msg, struct uni_xtraffic *ie,
+ u_int present, struct unicx *cx __unused)
+{
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FPCR0_P,
+ UNI_TRAFFIC_FPCR0_ID, ie->fpcr0);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BPCR0_P,
+ UNI_TRAFFIC_BPCR0_ID, ie->bpcr0);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FPCR1_P,
+ UNI_TRAFFIC_FPCR1_ID, ie->fpcr1);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BPCR1_P,
+ UNI_TRAFFIC_BPCR1_ID, ie->bpcr1);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FSCR0_P,
+ UNI_TRAFFIC_FSCR0_ID, ie->fscr0);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BSCR0_P,
+ UNI_TRAFFIC_BSCR0_ID, ie->bscr0);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FSCR1_P,
+ UNI_TRAFFIC_FSCR1_ID, ie->fscr1);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BSCR1_P,
+ UNI_TRAFFIC_BSCR1_ID, ie->bscr1);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FMBS0_P,
+ UNI_TRAFFIC_FMBS0_ID, ie->fmbs0);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BMBS0_P,
+ UNI_TRAFFIC_BMBS0_ID, ie->bmbs0);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FMBS1_P,
+ UNI_TRAFFIC_FMBS1_ID, ie->fmbs1);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BMBS1_P,
+ UNI_TRAFFIC_BMBS1_ID, ie->bmbs1);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FABR1_P,
+ UNI_TRAFFIC_FABR1_ID, ie->fabr1);
+ APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BABR1_P,
+ UNI_TRAFFIC_BABR1_ID, ie->babr1);
+
+ APP_OPT(msg, present, UNI_TRAFFIC_BEST_P,
+ UNI_TRAFFIC_BEST_ID);
+ APP_OPT_BYTE(msg, present, UNI_TRAFFIC_MOPT_P,
+ UNI_TRAFFIC_MOPT_ID,
+ (ie->ftag ? UNI_TRAFFIC_FTAG : 0) |
+ (ie->btag ? UNI_TRAFFIC_BTAG : 0) |
+ (ie->fdisc ? UNI_TRAFFIC_FDISC : 0) |
+ (ie->fdisc ? UNI_TRAFFIC_BDISC : 0));
+
+ return 0;
+}
+
+static int
+decode_traffic_common(struct uni_xtraffic *ie, struct uni_msg *msg,
+ u_int ielen, u_int *present)
+{
+ u_char c;
+
+ while(ielen--) {
+ switch(c = *msg->b_rptr++) {
+
+ default:
+ rej:
+ return -1;
+
+ DEC_GETF3(TRAFFIC_FPCR0, fpcr0, *present);
+ DEC_GETF3(TRAFFIC_BPCR0, bpcr0, *present);
+ DEC_GETF3(TRAFFIC_FPCR1, fpcr1, *present);
+ DEC_GETF3(TRAFFIC_BPCR1, bpcr1, *present);
+ DEC_GETF3(TRAFFIC_FSCR0, fscr0, *present);
+ DEC_GETF3(TRAFFIC_BSCR0, bscr0, *present);
+ DEC_GETF3(TRAFFIC_FSCR1, fscr1, *present);
+ DEC_GETF3(TRAFFIC_BSCR1, bscr1, *present);
+ DEC_GETF3(TRAFFIC_FMBS0, fmbs0, *present);
+ DEC_GETF3(TRAFFIC_BMBS0, bmbs0, *present);
+ DEC_GETF3(TRAFFIC_BMBS1, bmbs1, *present);
+ DEC_GETF3(TRAFFIC_FABR1, fabr1, *present);
+ DEC_GETF3(TRAFFIC_BABR1, babr1, *present);
+
+ case UNI_TRAFFIC_BEST_ID:
+ *present |= UNI_TRAFFIC_BEST_P;
+ break;
+
+ case UNI_TRAFFIC_MOPT_ID:
+ if(ielen == 0)
+ return -1;
+ ielen--;
+ if(!(*present & UNI_TRAFFIC_MOPT_P)) {
+ *present |= UNI_TRAFFIC_MOPT_P;
+ ie->ftag = (*msg->b_rptr&UNI_TRAFFIC_FTAG)?1:0;
+ ie->btag = (*msg->b_rptr&UNI_TRAFFIC_BTAG)?1:0;
+ ie->fdisc = (*msg->b_rptr&UNI_TRAFFIC_FDISC)?1:0;
+ ie->bdisc = (*msg->b_rptr&UNI_TRAFFIC_BDISC)?1:0;
+ }
+ msg->b_rptr++;
+ break;
+ }
+ }
+ return 0;
+}
+
+
+/*****************************************************************/
+
+DEF_IE_PRINT(itu, traffic)
+{
+ if(uni_print_iehdr("traffic", &ie->h, cx))
+ return;
+ print_ie_traffic_common(cx, ie->h.present, &ie->t);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, traffic)
+{
+ return check_ie_traffic_common(&ie->t, ie->h.present, cx);
+}
+
+DEF_IE_ENCODE(itu, traffic)
+{
+ START_IE(traffic, UNI_IE_TRAFFIC, 26);
+ encode_traffic_common(msg, &ie->t, ie->h.present, cx);
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, traffic)
+{
+ IE_START(;);
+
+ if(ielen > 30)
+ goto rej;
+
+ if(decode_traffic_common(&ie->t, msg, ielen, &ie->h.present))
+ goto rej;
+
+ IE_END(TRAFFIC);
+}
+
+/*****************************************************************/
+
+DEF_IE_PRINT(itu, atraffic)
+{
+ if(uni_print_iehdr("atraffic", &ie->h, cx))
+ return;
+ print_ie_traffic_common(cx, ie->h.present, &ie->t);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, atraffic)
+{
+ return check_ie_traffic_common(&ie->t, ie->h.present, cx);
+}
+
+DEF_IE_ENCODE(itu, atraffic)
+{
+ START_IE(traffic, UNI_IE_ATRAFFIC, 26);
+ encode_traffic_common(msg, &ie->t, ie->h.present, cx);
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, atraffic)
+{
+ IE_START(;);
+
+ if(ielen > 30)
+ goto rej;
+
+ if(decode_traffic_common(&ie->t, msg, ielen, &ie->h.present))
+ goto rej;
+
+ IE_END(ATRAFFIC);
+}
+
+/*****************************************************************/
+
+DEF_IE_PRINT(itu, mintraffic)
+{
+ if(uni_print_iehdr("mintraffic", &ie->h, cx))
+ return;
+
+ uni_print_entry(cx, "pcr0", "(");
+ if(ie->h.present & UNI_MINTRAFFIC_FPCR0_P)
+ uni_printf(cx, "%u", ie->fpcr0);
+ uni_putc(',', cx);
+ if(ie->h.present & UNI_MINTRAFFIC_BPCR0_P)
+ uni_printf(cx, "%u", ie->bpcr0);
+ uni_putc(')', cx);
+
+ uni_print_entry(cx, "pcr1", "(");
+ if(ie->h.present & UNI_MINTRAFFIC_FPCR1_P)
+ uni_printf(cx, "%u", ie->fpcr1);
+ uni_putc(',', cx);
+ if(ie->h.present & UNI_MINTRAFFIC_BPCR1_P)
+ uni_printf(cx, "%u", ie->bpcr1);
+ uni_putc(')', cx);
+
+ uni_print_entry(cx, "abr1", "(");
+ if(ie->h.present & UNI_MINTRAFFIC_FABR1_P)
+ uni_printf(cx, "%u", ie->fabr1);
+ uni_putc(',', cx);
+ if(ie->h.present & UNI_MINTRAFFIC_BABR1_P)
+ uni_printf(cx, "%u", ie->babr1);
+ uni_printf(cx, ")");
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, mintraffic)
+{
+ u_int abr;
+ u_int xbr;
+ UNUSED(cx);
+
+ abr = ie->h.present & (UNI_MINTRAFFIC_FABR1_P|UNI_MINTRAFFIC_BABR1_P);
+ xbr = ie->h.present & (UNI_MINTRAFFIC_FPCR0_P|UNI_MINTRAFFIC_BPCR0_P|
+ UNI_MINTRAFFIC_FPCR1_P|UNI_MINTRAFFIC_BPCR1_P);
+
+ if(abr && xbr)
+ return -1;
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, mintraffic)
+{
+ START_IE(mintraffic, UNI_IE_MINTRAFFIC, 16);
+
+ APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FPCR0_P,
+ UNI_TRAFFIC_FPCR0_ID, ie->fpcr0);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BPCR0_P,
+ UNI_TRAFFIC_BPCR0_ID, ie->bpcr0);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FPCR1_P,
+ UNI_TRAFFIC_FPCR1_ID, ie->fpcr1);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BPCR1_P,
+ UNI_TRAFFIC_BPCR1_ID, ie->bpcr1);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FABR1_P,
+ UNI_TRAFFIC_FABR1_ID, ie->fabr1);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BABR1_P,
+ UNI_TRAFFIC_BABR1_ID, ie->babr1);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, mintraffic)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen > 20)
+ goto rej;
+
+ while(ielen--) {
+ switch(c = *msg->b_rptr++) {
+
+ default:
+ goto rej;
+
+ DEC_GETF3(MINTRAFFIC_FPCR0, fpcr0, ie->h.present);
+ DEC_GETF3(MINTRAFFIC_BPCR0, bpcr0, ie->h.present);
+ DEC_GETF3(MINTRAFFIC_FPCR1, fpcr1, ie->h.present);
+ DEC_GETF3(MINTRAFFIC_BPCR1, bpcr1, ie->h.present);
+ DEC_GETF3(MINTRAFFIC_FABR1, fabr1, ie->h.present);
+ DEC_GETF3(MINTRAFFIC_BABR1, babr1, ie->h.present);
+ }
+ }
+
+ IE_END(MINTRAFFIC);
+}
+
+/*****************************************************************/
+
+DEF_IE_PRINT(net, mdcr)
+{
+ static const struct uni_print_tbl origin_tbl[] = {
+ MKT(UNI_MDCR_ORIGIN_USER, user),
+ MKT(UNI_MDCR_ORIGIN_NET, net),
+ EOT()
+ };
+
+ if(uni_print_iehdr("mdcr", &ie->h, cx))
+ return;
+
+ uni_print_tbl("origin", ie->origin, origin_tbl, cx);
+ uni_print_entry(cx, "mdcr", "(");
+ uni_printf(cx, "%u", ie->fmdcr);
+ uni_putc(',', cx);
+ uni_printf(cx, "%u", ie->bmdcr);
+ uni_putc(')', cx);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, mdcr)
+{
+ UNUSED(cx);
+
+ if ((ie->origin != UNI_MDCR_ORIGIN_USER &&
+ ie->origin != UNI_MDCR_ORIGIN_NET) ||
+ ie->fmdcr >= (1 << 24) || ie->bmdcr >= (1 << 24))
+ return (-1);
+
+ return (0);
+}
+
+DEF_IE_ENCODE(net, mdcr)
+{
+ START_IE(mdcr, UNI_IE_MDCR, 9);
+
+ APP_BYTE(msg, ie->origin);
+ APP_SUB_24BIT(msg, UNI_TRAFFIC_FMDCR_ID, ie->fmdcr);
+ APP_SUB_24BIT(msg, UNI_TRAFFIC_BMDCR_ID, ie->bmdcr);
+
+ SET_IE_LEN(msg);
+ return (0);
+}
+
+DEF_IE_DECODE(net, mdcr)
+{
+ u_char c;
+#define UNI_TRAFFIC_FMDCR_P 0x01
+#define UNI_TRAFFIC_BMDCR_P 0x02
+ u_int p = 0;
+
+ IE_START(;);
+
+ if(ielen != 9)
+ goto rej;
+
+ ie->origin = *msg->b_rptr++;
+ ielen--;
+
+ while(ielen--) {
+ switch(c = *msg->b_rptr++) {
+
+ default:
+ goto rej;
+
+ DEC_GETF3(TRAFFIC_FMDCR, fmdcr, p);
+ DEC_GETF3(TRAFFIC_BMDCR, bmdcr, p);
+ }
+ }
+ if (p != (UNI_TRAFFIC_FMDCR_P | UNI_TRAFFIC_BMDCR_P))
+ goto rej;
+
+ IE_END(MDCR);
+}
+
+/*********************************************************************
+ *
+ * Connection identifier
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 69...70
+ * UNI4.0 pp. 15...16
+ * PNNI1.0 p. 198
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, connid)
+{
+ static const struct uni_print_tbl tbl[] = {
+ MKT(UNI_CONNID_VCI, exclusive),
+ MKT(UNI_CONNID_ANYVCI, any),
+ MKT(UNI_CONNID_NOVCI, no),
+ EOT()
+ };
+ static const struct uni_print_tbl assoc_tbl[] = {
+ MKT(UNI_CONNID_ASSOC, associated),
+ MKT(UNI_CONNID_NONASSOC,non-associated),
+ EOT()
+ };
+
+ if(uni_print_iehdr("connid", &ie->h, cx))
+ return;
+
+ uni_print_tbl("mode", ie->assoc, assoc_tbl, cx);
+ uni_print_entry(cx, "connid", "(%u,", ie->vpci);
+ if(ie->type == UNI_CONNID_VCI)
+ uni_printf(cx, "%u", ie->vci);
+ else
+ uni_print_tbl(NULL, ie->type, tbl, cx);
+ uni_printf(cx, ")");
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, connid)
+{
+ UNUSED(cx);
+ switch(ie->type) {
+ default:
+ return -1;
+ case UNI_CONNID_VCI:
+ case UNI_CONNID_ANYVCI:
+ case UNI_CONNID_NOVCI:
+ break;
+ }
+
+#if 0
+ /*
+ * This field must be checked by the application to fulfil
+ * Q.2931Amd4 27) 5.2.3 last sentence
+ */
+ switch(ie->assoc) {
+
+ case UNI_CONNID_ASSOC:
+ if(!cx->cx.pnni)
+ return -1;
+ break;
+
+ case UNI_CONNID_NONASSOC:
+ break;
+
+ default:
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, connid)
+{
+ START_IE(connid, UNI_IE_CONNID, 5);
+
+ APP_BYTE(msg, 0x80 | (ie->assoc << 3) | ie->type);
+ APP_BYTE(msg, ie->vpci >> 8);
+ APP_BYTE(msg, ie->vpci >> 0);
+ APP_BYTE(msg, ie->vci >> 8);
+ APP_BYTE(msg, ie->vci >> 0);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, connid)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen != 5)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ if((c & 0x80) == 0)
+ goto rej;
+ ie->assoc = (c >> 3) & 3;
+ ie->type = c & 7;
+ ie->vpci = *msg->b_rptr++ << 8;
+ ie->vpci |= *msg->b_rptr++;
+ ie->vci = *msg->b_rptr++ << 8;
+ ie->vci |= *msg->b_rptr++;
+
+ IE_END(CONNID);
+}
+
+/*********************************************************************
+ *
+ * Quality of Service
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 72
+ * UNI4.0 pp. 16...17
+ */
+
+static void
+print_qos(struct unicx *cx, struct uni_ie_qos *ie)
+{
+ static const struct uni_print_tbl class_tbl[] = {
+ MKT(UNI_QOS_CLASS0, Class0),
+ MKT(UNI_QOS_CLASS1, Class1),
+ MKT(UNI_QOS_CLASS2, Class2),
+ MKT(UNI_QOS_CLASS3, Class3),
+ MKT(UNI_QOS_CLASS4, Class4),
+ EOT()
+ };
+
+ if(uni_print_iehdr("qos", &ie->h, cx))
+ return;
+
+ uni_print_tbl("fwd", ie->fwd, class_tbl, cx);
+ uni_print_tbl("bwd", ie->bwd, class_tbl, cx);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_PRINT(itu, qos)
+{
+ print_qos(cx, ie);
+}
+DEF_IE_PRINT(net, qos)
+{
+ print_qos(cx, ie);
+}
+
+DEF_IE_CHECK(itu, qos)
+{
+ UNUSED(cx);
+
+ switch(ie->fwd) {
+ default:
+ return -1;
+
+ case UNI_QOS_CLASS0:
+ break;
+ }
+ switch(ie->bwd) {
+ default:
+ return -1;
+
+ case UNI_QOS_CLASS0:
+ break;
+ }
+ return 0;
+}
+
+DEF_IE_CHECK(net, qos)
+{
+ UNUSED(cx);
+
+ switch(ie->fwd) {
+ default:
+ return -1;
+
+ case UNI_QOS_CLASS1:
+ case UNI_QOS_CLASS2:
+ case UNI_QOS_CLASS3:
+ case UNI_QOS_CLASS4:
+ break;
+ }
+ switch(ie->bwd) {
+ default:
+ return -1;
+
+ case UNI_QOS_CLASS1:
+ case UNI_QOS_CLASS2:
+ case UNI_QOS_CLASS3:
+ case UNI_QOS_CLASS4:
+ break;
+ }
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, qos)
+{
+ START_IE(qos, UNI_IE_QOS, 2);
+
+ APP_BYTE(msg, ie->fwd);
+ APP_BYTE(msg, ie->bwd);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+DEF_IE_ENCODE(net, qos)
+{
+ START_IE(qos, UNI_IE_QOS, 2);
+
+ APP_BYTE(msg, ie->fwd);
+ APP_BYTE(msg, ie->bwd);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, qos)
+{
+ IE_START(;);
+
+ if(ielen != 2)
+ goto rej;
+
+ ie->fwd = *msg->b_rptr++;
+ ie->bwd = *msg->b_rptr++;
+
+ IE_END(QOS);
+}
+
+DEF_IE_DECODE(net, qos)
+{
+ IE_START(;);
+
+ if(ielen != 2)
+ goto rej;
+
+ ie->fwd = *msg->b_rptr++;
+ ie->bwd = *msg->b_rptr++;
+
+ IE_END(QOS);
+}
+
+/*********************************************************************
+ *
+ * Broadband Lower Layer Information
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 53...54
+ * UNI4.0 p. 12
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, bhli)
+{
+ static const struct uni_print_tbl type_tbl[] = {
+ MKT(UNI_BHLI_ISO, iso),
+ MKT(UNI_BHLI_USER, user),
+ MKT(UNI_BHLI_VENDOR, vendor),
+ EOT()
+ };
+ u_int i;
+
+ if(uni_print_iehdr("bhli", &ie->h, cx))
+ return;
+
+ uni_print_tbl("type", ie->type, type_tbl, cx);
+ uni_print_entry(cx, "len", "%d", ie->len);
+ uni_print_entry(cx, "info", "(");
+ for(i = 0; i < ie->len; i++)
+ uni_printf(cx, ",0x%02x", ie->info[i]);
+ uni_printf(cx, ")");
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, bhli)
+{
+ UNUSED(cx);
+
+ switch(ie->type) {
+ default:
+ return -1;
+
+ case UNI_BHLI_ISO:
+ case UNI_BHLI_USER:
+ case UNI_BHLI_VENDOR:
+ break;
+ }
+ if(ie->len > 8)
+ return -1;
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, bhli)
+{
+ START_IE(bhli, UNI_IE_BHLI, 9);
+
+ APP_BYTE(msg, 0x80 | ie->type);
+ APP_BUF(msg, ie->info, ie->len);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, bhli)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen > 9)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ ielen--;
+
+ if(!(c & 0x80))
+ goto rej;
+ ie->type = c & 0x7f;
+ ie->len = ielen;
+ (void)memcpy(ie->info, msg->b_rptr, ielen);
+ msg->b_rptr += ielen;
+
+ IE_END(BHLI);
+}
+
+/*********************************************************************
+ *
+ * Broadband bearer capabilities
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 51...52
+ * Q.2931 Amd 1
+ * UNI4.0 pp. 10...12, 106...109
+ *
+ * UNI4.0 changed the meaning of byte 5a. Instead of 3 bit traffic type and
+ * 2 bit timing requirements there are now 7 bits ATM transfer capabilities.
+ * However the old format is still supported: it should be recognized on
+ * input, but never be generated on output. Mapping is left to the user of
+ * UNI.
+ *
+ * Amd 1 not checked XXX.
+ *
+ * The Appendix in UNI4.0 lists all the supported combinations of various
+ * traffic IE's. The check function implements part of it.
+ *
+ * A C X VP
+ * 1 CBR.1 7 . 7 7
+ * 2 CBR.2 - . 4,5,6 5 (*)
+ * 3 CBR.3 - . 4,5,6 5 (*)
+ * 4 rt-VBR.1 . 19 19 19
+ * 5 rt-VBR.2 . 9 1,9 9
+ * 6 rt-VBR.3 . 9 1,9 9
+ * 7 rt-VBR.4 . . 1,9 . (*)
+ * 8 rt-VBR.5 . . 1,9 . (*)
+ * 9 rt-VBR.6 . 9 1,9 9 (*)
+ * 10 nrt-VBR.1 . 11 11 11
+ * 11 nrt-VBR.2 . - -,0,2,8,10 -,10
+ * 12 nrt-VBR.3 . - -,0,2,8,10 -,10
+ * 13 nrt-VBR.4 . - -,0,2,8,10 . (*)
+ * 14 nrt-VBR.5 . - -,0,2,8,10 . (*)
+ * 15 nrt-VBR.6 . - -,0,2,8,10 -,10(*)
+ * 16 ABR . 12 12 12
+ * 17 UBR.1 . - -,0,2,8,10 -,10
+ * 18 UBR.2 . - -,0,2,8,10 -,10
+ *
+ * (*) compatibility
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, bearer)
+{
+ static const struct uni_print_tbl bclass_tbl[] = {
+ MKT(UNI_BEARER_A, bcob-A),
+ MKT(UNI_BEARER_C, bcob-C),
+ MKT(UNI_BEARER_X, bcob-X),
+ MKT(UNI_BEARER_TVP, transparent-VP),
+ EOT()
+ };
+ static const struct uni_print_tbl atc_tbl[] = {
+ MKT(UNI_BEARER_ATC_CBR, cbr),
+ MKT(UNI_BEARER_ATC_CBR1, cbr1),
+ MKT(UNI_BEARER_ATC_VBR, vbr),
+ MKT(UNI_BEARER_ATC_VBR1, vbr1),
+ MKT(UNI_BEARER_ATC_NVBR, nvbr),
+ MKT(UNI_BEARER_ATC_NVBR1, nvbr1),
+ MKT(UNI_BEARER_ATC_ABR, abr),
+
+ MKT(UNI_BEARER_ATCX_0, x0),
+ MKT(UNI_BEARER_ATCX_1, x1),
+ MKT(UNI_BEARER_ATCX_2, x2),
+ MKT(UNI_BEARER_ATCX_4, x4),
+ MKT(UNI_BEARER_ATCX_6, x6),
+ MKT(UNI_BEARER_ATCX_8, x8),
+ EOT()
+ };
+ static const struct uni_print_tbl cfg_tbl[] = {
+ MKT(UNI_BEARER_P2P, p2p),
+ MKT(UNI_BEARER_MP, mp),
+ EOT()
+ };
+ static const struct uni_print_tbl clip_tbl[] = {
+ MKT(UNI_BEARER_NOCLIP, no),
+ MKT(UNI_BEARER_CLIP, yes),
+ EOT()
+ };
+
+ if(uni_print_iehdr("bearer", &ie->h, cx))
+ return;
+
+ uni_print_tbl("class", ie->bclass, bclass_tbl, cx);
+
+ if(ie->h.present & UNI_BEARER_ATC_P) {
+ uni_print_tbl("atc", ie->atc, atc_tbl, cx);
+ }
+ uni_print_tbl("clip", ie->clip, clip_tbl, cx);
+ uni_print_tbl("cfg", ie->cfg, cfg_tbl, cx);
+
+ uni_print_ieend(cx);
+}
+
+#define QTYPE(C,A) ((UNI_BEARER_##C << 8) | UNI_BEARER_ATC_##A)
+#define QTYPEX(C,A) ((UNI_BEARER_##C << 8) | UNI_BEARER_ATCX_##A)
+#define QTYPE0(C) ((UNI_BEARER_##C << 8) | (1 << 16))
+DEF_IE_CHECK(itu, bearer)
+{
+ UNUSED(cx);
+
+ switch((ie->bclass << 8) |
+ ((ie->h.present & UNI_BEARER_ATC_P) == 0
+ ? (1 << 16)
+ : ie->atc)) {
+
+ default:
+ return -1;
+
+ case QTYPE (A, CBR1): /* 1 */
+ case QTYPE (X, CBR1): /* 1 */
+ case QTYPE (TVP, CBR1): /* 1 */
+
+ case QTYPE0(A): /* 2,3 */
+ case QTYPEX(X, 4): /* 2,3 */
+ case QTYPE (X, CBR): /* 2,3 */
+ case QTYPEX(X, 6): /* 2,3 */
+ case QTYPE (TVP, CBR): /* 2,3 */
+
+ case QTYPE (C, VBR1): /* 4 */
+ case QTYPE (X, VBR1): /* 4 */
+ case QTYPE (TVP, VBR1): /* 4 */
+
+ case QTYPE (C, VBR): /* 5,6,9 */
+ case QTYPEX(X, 1): /* 5,6,7,8,9 */
+ case QTYPE (X, VBR): /* 5,6,7,8,9 */
+ case QTYPE (TVP, VBR): /* 5,6,9 */
+
+ case QTYPE (C, NVBR1): /* 10 */
+ case QTYPE (X, NVBR1): /* 10 */
+ case QTYPE (TVP, NVBR1): /* 10 */
+
+ case QTYPE0(C): /* 11,12,13,14,15,17,18 */
+ case QTYPE0(X): /* 11,12,13,14,15,17,18 */
+ case QTYPEX(X, 0): /* 11,12,13,14,15,17,18 */
+ case QTYPEX(X, 2): /* 11,12,13,14,15,17,18 */
+ case QTYPEX(X, 8): /* 11,12,13,14,15,17,18 */
+ case QTYPE (X, NVBR): /* 11,12,13,14,15,17,18 */
+ case QTYPE0(TVP): /* 11,12,15,17,18 */
+ case QTYPE (TVP, NVBR): /* 11,12,15,17,18 */
+
+ case QTYPE (C, ABR): /* 16 */
+ case QTYPE (X, ABR): /* 16 */
+ case QTYPE (TVP, ABR): /* 16 */
+ break;
+ }
+
+ switch(ie->clip) {
+ default:
+ return -1;
+
+ case UNI_BEARER_NOCLIP:
+ case UNI_BEARER_CLIP:
+ break;
+ }
+ switch(ie->cfg) {
+ default:
+ return -1;
+
+ case UNI_BEARER_P2P:
+ case UNI_BEARER_MP:
+ break;
+ }
+
+ return 0;
+}
+#undef QTYPE
+#undef QTYPEX
+#undef QTYPE0
+
+DEF_IE_ENCODE(itu, bearer)
+{
+ START_IE(bearer, UNI_IE_BEARER, 3);
+
+ APP_BYTE(msg, ie->bclass |
+ ((ie->h.present & UNI_BEARER_ATC_P) ? 0:0x80));
+ APP_OPT(msg, ie->h.present, UNI_BEARER_ATC_P,
+ 0x80 | ie->atc);
+ APP_BYTE(msg, 0x80 | (ie->clip << 5) | ie->cfg);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, bearer)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen != 2 && ielen != 3)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ ielen--;
+ ie->bclass = c & 0x1f;
+ if(!(c & 0x80)) {
+ c = *msg->b_rptr++;
+ ielen--;
+ ie->h.present |= UNI_BEARER_ATC_P;
+
+ switch(c & 0x7f) {
+ /*
+ * Real legal values
+ */
+ case UNI_BEARER_ATC_CBR:
+ case UNI_BEARER_ATC_CBR1:
+ case UNI_BEARER_ATC_VBR:
+ case UNI_BEARER_ATC_VBR1:
+ case UNI_BEARER_ATC_NVBR:
+ case UNI_BEARER_ATC_NVBR1:
+ case UNI_BEARER_ATC_ABR:
+ break;
+
+ /*
+ * Compat values
+ */
+ case UNI_BEARER_ATCX_0:
+ case UNI_BEARER_ATCX_1:
+ case UNI_BEARER_ATCX_2:
+ case UNI_BEARER_ATCX_4:
+ case UNI_BEARER_ATCX_6:
+ case UNI_BEARER_ATCX_8:
+ break;
+
+ default:
+ goto rej;
+ }
+
+ if(!(c & 0x80))
+ goto rej;
+
+ ie->atc = c & 0x7f;
+ }
+ if(ielen == 0)
+ goto rej;
+ c = *msg->b_rptr++;
+ ielen--;
+ if(!(c & 0x80))
+ goto rej;
+ ie->clip = (c >> 5) & 0x3;
+ ie->cfg = c & 0x3;
+
+ IE_END(BEARER);
+}
+
+/*********************************************************************
+ *
+ * Broadband Lower Layer Information
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 54...59
+ * UNI4.0 pp. 12...14
+ *
+ * UNI4.0 states, that layer 1 info is not supported.
+ * We allow a layer 1 protocol identifier.
+ *
+ * UNI4.0 states, that the layer information subelements are NOT position
+ * dependent. We allow them in any order on input, but generate always the
+ * definit order on output.
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, blli)
+{
+ static const struct uni_print_tbl l2_tbl[] = {
+ MKT(UNI_BLLI_L2_BASIC, basic),
+ MKT(UNI_BLLI_L2_Q921, Q921),
+ MKT(UNI_BLLI_L2_X25LL, X25-LL),
+ MKT(UNI_BLLI_L2_X25ML, X25-ML),
+ MKT(UNI_BLLI_L2_LABP, LAPB),
+ MKT(UNI_BLLI_L2_HDLC_ARM, HDLC-ARM),
+ MKT(UNI_BLLI_L2_HDLC_NRM, HDLC-NRM),
+ MKT(UNI_BLLI_L2_HDLC_ABM, HDLC-ABM),
+ MKT(UNI_BLLI_L2_LAN, LAN),
+ MKT(UNI_BLLI_L2_X75, X75),
+ MKT(UNI_BLLI_L2_Q922, Q922),
+ MKT(UNI_BLLI_L2_USER, user),
+ MKT(UNI_BLLI_L2_ISO7776, ISO7776),
+ EOT()
+ };
+ static const struct uni_print_tbl l2mode_tbl[] = {
+ MKT(UNI_BLLI_L2NORM, normal),
+ MKT(UNI_BLLI_L2EXT, extended),
+ EOT()
+ };
+ static const struct uni_print_tbl l3_tbl[] = {
+ MKT(UNI_BLLI_L3_X25, X25),
+ MKT(UNI_BLLI_L3_ISO8208, ISO8208),
+ MKT(UNI_BLLI_L3_X223, X223),
+ MKT(UNI_BLLI_L3_CLMP, CLMP),
+ MKT(UNI_BLLI_L3_T70, T70),
+ MKT(UNI_BLLI_L3_TR9577, TR9577),
+ MKT(UNI_BLLI_L3_USER, user),
+ MKT(UNI_BLLI_L3_H310, H310),
+ MKT(UNI_BLLI_L3_H321, H321),
+ EOT()
+ };
+ static const struct uni_print_tbl l3mode_tbl[] = {
+ MKT(UNI_BLLI_L3NSEQ, normal-seq),
+ MKT(UNI_BLLI_L3ESEQ, extended-seq),
+ EOT()
+ };
+ static const struct uni_print_tbl l3psiz_tbl[] = {
+ MKT(UNI_BLLI_L3_16, 16),
+ MKT(UNI_BLLI_L3_32, 32),
+ MKT(UNI_BLLI_L3_64, 64),
+ MKT(UNI_BLLI_L3_128, 128),
+ MKT(UNI_BLLI_L3_256, 256),
+ MKT(UNI_BLLI_L3_512, 512),
+ MKT(UNI_BLLI_L3_1024, 1024),
+ MKT(UNI_BLLI_L3_2048, 2048),
+ MKT(UNI_BLLI_L3_4096, 4096),
+ EOT()
+ };
+ static const struct uni_print_tbl l3ttype_tbl[] = {
+ MKT(UNI_BLLI_L3_TTYPE_RECV, receive_only),
+ MKT(UNI_BLLI_L3_TTYPE_SEND, send_only),
+ MKT(UNI_BLLI_L3_TTYPE_BOTH, both),
+ EOT()
+ };
+ static const struct uni_print_tbl l3mux_tbl[] = {
+ MKT(UNI_BLLI_L3_MUX_NOMUX, NOMUX),
+ MKT(UNI_BLLI_L3_MUX_TS, TS),
+ MKT(UNI_BLLI_L3_MUX_TSFEC, TSFEC),
+ MKT(UNI_BLLI_L3_MUX_PS, PS),
+ MKT(UNI_BLLI_L3_MUX_PSFEC, PSFEC),
+ MKT(UNI_BLLI_L3_MUX_H221, H221),
+ EOT()
+ };
+ static const struct uni_print_tbl l3tcap_tbl[] = {
+ MKT(UNI_BLLI_L3_TCAP_NOIND, noind),
+ MKT(UNI_BLLI_L3_TCAP_AAL1, aal1),
+ MKT(UNI_BLLI_L3_TCAP_AAL5, aal5),
+ MKT(UNI_BLLI_L3_TCAP_AAL15, aal1&5),
+ EOT()
+ };
+
+ if(uni_print_iehdr("blli", &ie->h, cx))
+ return;
+
+ if(ie->h.present & UNI_BLLI_L1_P) {
+ uni_print_entry(cx, "l1", "%u", ie->l1);
+ uni_print_eol(cx);
+ }
+ if(ie->h.present & UNI_BLLI_L2_P) {
+ uni_print_tbl("l2", ie->l2, l2_tbl, cx);
+ uni_print_push_prefix("l2", cx);
+ cx->indent++;
+ if(ie->h.present & UNI_BLLI_L2_USER_P)
+ uni_print_entry(cx, "proto", "%u", ie->l2_user);
+ if(ie->h.present & UNI_BLLI_L2_Q933_P) {
+ uni_print_entry(cx, "q933", "%u", ie->l2_q933);
+ uni_print_tbl("mode", ie->l2_mode, l2mode_tbl, cx);
+ }
+ if(ie->h.present & UNI_BLLI_L2_WSIZ_P)
+ uni_print_entry(cx, "wsize", "%u", ie->l2_wsiz);
+ uni_print_pop_prefix(cx);
+ cx->indent--;
+ uni_print_eol(cx);
+
+ }
+ if(ie->h.present & UNI_BLLI_L3_P) {
+ uni_print_tbl("l3", ie->l3, l3_tbl, cx);
+ uni_print_push_prefix("l3", cx);
+ cx->indent++;
+ if(ie->h.present & UNI_BLLI_L3_USER_P)
+ uni_print_entry(cx, "proto", "%u", ie->l3_user);
+ if(ie->h.present & UNI_BLLI_L3_MODE_P)
+ uni_print_tbl("mode", ie->l3_mode, l3mode_tbl, cx);
+ if(ie->h.present & UNI_BLLI_L3_PSIZ_P)
+ uni_print_tbl("packet-size", ie->l3_psiz, l3psiz_tbl, cx);
+ if(ie->h.present & UNI_BLLI_L3_WSIZ_P)
+ uni_print_entry(cx, "window-size", "%u", ie->l3_wsiz);
+ if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
+ uni_print_tbl("ttype", ie->l3_ttype, l3ttype_tbl, cx);
+ uni_print_tbl("tcap", ie->l3_tcap, l3tcap_tbl, cx);
+ }
+ if(ie->h.present & UNI_BLLI_L3_MUX_P) {
+ uni_print_tbl("fmux", ie->l3_fmux, l3mux_tbl, cx);
+ uni_print_tbl("bmux", ie->l3_bmux, l3mux_tbl, cx);
+ }
+ if(ie->h.present & UNI_BLLI_L3_IPI_P)
+ uni_print_entry(cx, "ipi", "0x%02x", ie->l3_ipi);
+ if(ie->h.present & UNI_BLLI_L3_SNAP_P)
+ uni_print_entry(cx, "snap", "%06x.%04x", ie->oui, ie->pid);
+ uni_print_pop_prefix(cx);
+ cx->indent--;
+ uni_print_eol(cx);
+ }
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, blli)
+{
+ UNUSED(cx);
+/*
+ if(ie->h.present & UNI_BLLI_L1_P)
+ ;
+*/
+
+ if(ie->h.present & UNI_BLLI_L2_P) {
+ static u_int mask =
+ UNI_BLLI_L2_Q933_P | UNI_BLLI_L2_WSIZ_P |
+ UNI_BLLI_L2_USER_P;
+
+ switch(ie->l2) {
+ default:
+ return -1;
+
+ case UNI_BLLI_L2_BASIC:
+ case UNI_BLLI_L2_Q921:
+ case UNI_BLLI_L2_LABP:
+ case UNI_BLLI_L2_LAN:
+ case UNI_BLLI_L2_X75:
+ if(ie->h.present & mask)
+ return -1;
+ break;
+
+ case UNI_BLLI_L2_X25LL:
+ case UNI_BLLI_L2_X25ML:
+ case UNI_BLLI_L2_HDLC_ARM:
+ case UNI_BLLI_L2_HDLC_NRM:
+ case UNI_BLLI_L2_HDLC_ABM:
+ case UNI_BLLI_L2_Q922:
+ case UNI_BLLI_L2_ISO7776:
+ switch(ie->h.present & mask) {
+ default:
+ return -1;
+
+ case 0:
+ case UNI_BLLI_L2_Q933_P:
+ case UNI_BLLI_L2_Q933_P | UNI_BLLI_L2_WSIZ_P:
+ break;
+ }
+ break;
+
+ case UNI_BLLI_L2_USER:
+ switch(ie->h.present & mask) {
+ default:
+ return -1;
+
+ case 0: /* XXX ? */
+ case UNI_BLLI_L2_USER_P:
+ break;
+ }
+ break;
+ }
+ if(ie->h.present & UNI_BLLI_L2_Q933_P) {
+ if(ie->l2_q933 != 0)
+ return -1;
+
+ switch(ie->l2_mode) {
+ default:
+ return -1;
+
+ case UNI_BLLI_L2NORM:
+ case UNI_BLLI_L2EXT:
+ break;
+ }
+ }
+ if(ie->h.present & UNI_BLLI_L2_WSIZ_P) {
+ if(ie->l2_wsiz == 0 || ie->l2_wsiz > 127)
+ return -1;
+ }
+ if(ie->h.present & UNI_BLLI_L2_USER_P) {
+ if(ie->l2_user > 127)
+ return -1;
+ }
+ }
+ if(ie->h.present & UNI_BLLI_L3_P) {
+ static u_int mask =
+ UNI_BLLI_L3_MODE_P | UNI_BLLI_L3_PSIZ_P |
+ UNI_BLLI_L3_WSIZ_P | UNI_BLLI_L3_USER_P |
+ UNI_BLLI_L3_IPI_P | UNI_BLLI_L3_SNAP_P |
+ UNI_BLLI_L3_TTYPE_P | UNI_BLLI_L3_MUX_P;
+
+ switch(ie->l3) {
+ default:
+ return -1;
+
+ case UNI_BLLI_L3_X25:
+ case UNI_BLLI_L3_ISO8208:
+ case UNI_BLLI_L3_X223:
+ switch(ie->h.present & mask) {
+ default:
+ return -1;
+
+ case 0:
+ case UNI_BLLI_L3_MODE_P:
+ case UNI_BLLI_L3_MODE_P |
+ UNI_BLLI_L3_PSIZ_P:
+ case UNI_BLLI_L3_MODE_P |
+ UNI_BLLI_L3_PSIZ_P |
+ UNI_BLLI_L3_WSIZ_P:
+ break;
+ }
+ break;
+
+ case UNI_BLLI_L3_CLMP:
+ case UNI_BLLI_L3_T70:
+ if(ie->h.present & mask)
+ return -1;
+ break;
+
+ case UNI_BLLI_L3_TR9577:
+ switch(ie->h.present & mask) {
+ default:
+ return -1;
+
+ case 0:
+ case UNI_BLLI_L3_IPI_P:
+ case UNI_BLLI_L3_IPI_P | UNI_BLLI_L3_SNAP_P:
+ break;
+ }
+ break;
+
+ case UNI_BLLI_L3_H310:
+ switch(ie->h.present & mask) {
+ default:
+ return -1;
+
+ case 0:
+ case UNI_BLLI_L3_TTYPE_P:
+ case UNI_BLLI_L3_TTYPE_P|UNI_BLLI_L3_MUX_P:
+ break;
+ }
+ break;
+
+ case UNI_BLLI_L3_USER:
+ switch(ie->h.present & mask) {
+ default:
+ return -1;
+
+ case 0: /* XXX ? */
+ case UNI_BLLI_L3_USER_P:
+ break;
+ }
+ break;
+ }
+ if(ie->h.present & UNI_BLLI_L3_MODE_P) {
+ switch(ie->l3_mode) {
+ default:
+ return -1;
+
+ case UNI_BLLI_L3NSEQ:
+ case UNI_BLLI_L3ESEQ:
+ break;
+ }
+ }
+ if(ie->h.present & UNI_BLLI_L3_PSIZ_P) {
+ switch(ie->l3_psiz) {
+ default:
+ return -1;
+
+ case UNI_BLLI_L3_16:
+ case UNI_BLLI_L3_32:
+ case UNI_BLLI_L3_64:
+ case UNI_BLLI_L3_128:
+ case UNI_BLLI_L3_256:
+ case UNI_BLLI_L3_512:
+ case UNI_BLLI_L3_1024:
+ case UNI_BLLI_L3_2048:
+ case UNI_BLLI_L3_4096:
+ break;
+ }
+ }
+ if(ie->h.present & UNI_BLLI_L3_WSIZ_P) {
+ if(ie->l3_wsiz == 0 || ie->l3_wsiz > 127)
+ return -1;
+ }
+ if(ie->h.present & UNI_BLLI_L3_IPI_P) {
+ if(ie->l3_ipi == UNI_BLLI_L3_SNAP) {
+ if(!(ie->h.present & UNI_BLLI_L3_SNAP_P))
+ return -1;
+ } else {
+ if(ie->h.present & UNI_BLLI_L3_SNAP_P)
+ return -1;
+ }
+ }
+ if(ie->h.present & UNI_BLLI_L3_USER_P) {
+ if(ie->l3_user > 127)
+ return -1;
+ }
+ if(ie->h.present & UNI_BLLI_L3_SNAP_P) {
+ if(ie->oui >= (1<<24))
+ return -1;
+ if(ie->pid >= (1<<16))
+ return -1;
+ }
+ if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
+ switch(ie->l3_ttype) {
+ default:
+ return -1;
+
+ case UNI_BLLI_L3_TTYPE_RECV:
+ case UNI_BLLI_L3_TTYPE_SEND:
+ case UNI_BLLI_L3_TTYPE_BOTH:
+ break;
+ }
+ switch(ie->l3_tcap) {
+ default:
+ return -1;
+
+ case UNI_BLLI_L3_TCAP_NOIND:
+ case UNI_BLLI_L3_TCAP_AAL1:
+ case UNI_BLLI_L3_TCAP_AAL5:
+ case UNI_BLLI_L3_TCAP_AAL15:
+ break;
+ }
+ }
+ if(ie->h.present & UNI_BLLI_L3_MUX_P) {
+ switch(ie->l3_fmux) {
+ default:
+ return -1;
+
+ case UNI_BLLI_L3_MUX_NOMUX:
+ case UNI_BLLI_L3_MUX_TS:
+ case UNI_BLLI_L3_MUX_TSFEC:
+ case UNI_BLLI_L3_MUX_PS:
+ case UNI_BLLI_L3_MUX_PSFEC:
+ case UNI_BLLI_L3_MUX_H221:
+ break;
+ }
+ switch(ie->l3_bmux) {
+ default:
+ return -1;
+
+ case UNI_BLLI_L3_MUX_NOMUX:
+ case UNI_BLLI_L3_MUX_TS:
+ case UNI_BLLI_L3_MUX_TSFEC:
+ case UNI_BLLI_L3_MUX_PS:
+ case UNI_BLLI_L3_MUX_PSFEC:
+ case UNI_BLLI_L3_MUX_H221:
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, blli)
+{
+ START_IE(blli, UNI_IE_BLLI, 13);
+
+ if (IE_ISERROR(*ie)) {
+ APP_BYTE(msg, 0xff);
+ APP_BYTE(msg, 0xff);
+ goto out;
+ }
+
+ if(ie->h.present & UNI_BLLI_L1_P)
+ APP_BYTE(msg, (UNI_BLLI_L1_ID<<5)|ie->l1|0x80);
+
+ if(ie->h.present & UNI_BLLI_L2_P) {
+ if(ie->h.present & UNI_BLLI_L2_Q933_P) {
+ APP_BYTE(msg, (UNI_BLLI_L2_ID<<5)|ie->l2);
+ if(ie->h.present & UNI_BLLI_L2_WSIZ_P) {
+ APP_BYTE(msg, (ie->l2_mode<<5)|ie->l2_q933);
+ APP_BYTE(msg, ie->l2_wsiz | 0x80);
+ } else {
+ APP_BYTE(msg, (ie->l2_mode<<5)|ie->l2_q933|0x80);
+ }
+ } else if(ie->h.present & UNI_BLLI_L2_USER_P) {
+ APP_BYTE(msg, (UNI_BLLI_L2_ID<<5)|ie->l2);
+ APP_BYTE(msg, ie->l2_user | 0x80);
+ } else {
+ APP_BYTE(msg, (UNI_BLLI_L2_ID << 5) | ie->l2 | 0x80);
+ }
+ }
+
+ if(ie->h.present & UNI_BLLI_L3_P) {
+ if(ie->h.present & UNI_BLLI_L3_MODE_P) {
+ if(ie->h.present & UNI_BLLI_L3_PSIZ_P) {
+ if(ie->h.present & UNI_BLLI_L3_WSIZ_P) {
+ APP_BYTE(msg,(UNI_BLLI_L3_ID<<5)|ie->l3);
+ APP_BYTE(msg,(ie->l3_mode<<5));
+ APP_BYTE(msg,ie->l3_psiz);
+ APP_BYTE(msg,ie->l3_wsiz|0x80);
+ } else {
+ APP_BYTE(msg,(UNI_BLLI_L3_ID<<5)|ie->l3);
+ APP_BYTE(msg,(ie->l3_mode<<5));
+ APP_BYTE(msg,(ie->l3_psiz|0x80));
+ }
+ } else {
+ APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
+ APP_BYTE(msg, (ie->l3_mode<<5)|0x80);
+ }
+ } else if(ie->h.present & UNI_BLLI_L3_USER_P) {
+ APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
+ APP_BYTE(msg,(ie->l3_user|0x80));
+ } else if(ie->h.present & UNI_BLLI_L3_IPI_P) {
+ APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
+ APP_BYTE(msg,((ie->l3_ipi>>1) & 0x7f));
+ APP_BYTE(msg,(((ie->l3_ipi&1)<<6)|0x80));
+ if(ie->h.present & UNI_BLLI_L3_SNAP_P) {
+ APP_BYTE(msg, 0x80);
+ APP_BYTE(msg, (ie->oui >> 16));
+ APP_BYTE(msg, (ie->oui >> 8));
+ APP_BYTE(msg, (ie->oui >> 0));
+ APP_BYTE(msg, (ie->pid >> 8));
+ APP_BYTE(msg, (ie->pid >> 0));
+ }
+ } else if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
+ if(ie->h.present & UNI_BLLI_L3_MUX_P) {
+ APP_BYTE(msg, ie->l3_ttype | (ie->l3_tcap << 4));
+ APP_BYTE(msg, 0x80 | (ie->l3_fmux << 3) | ie->l3_bmux);
+ } else {
+ APP_BYTE(msg, 0x80 | ie->l3_ttype | (ie->l3_tcap << 4));
+ }
+ } else {
+ APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3|0x80);
+ }
+ }
+
+ out:
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, blli)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen > 17)
+ goto rej;
+
+ while(ielen--) {
+ switch(((c = *msg->b_rptr++) >> 5) & 0x3) {
+ default:
+ goto rej;
+
+ case UNI_BLLI_L1_ID:
+ ie->h.present |= UNI_BLLI_L1_P;
+ ie->l1 = c & 0x1f;
+ if(!(c & 0x80))
+ goto rej;
+ break;
+
+ case UNI_BLLI_L2_ID:
+ ie->h.present |= UNI_BLLI_L2_P;
+ ie->l2 = c & 0x1f;
+ if(!(c & 0x80)) {
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+ if(ie->l2 == UNI_BLLI_L2_USER) {
+ ie->h.present |= UNI_BLLI_L2_USER_P;
+ ie->l2_user = c & 0x7f;
+ if(!(c & 0x80))
+ goto rej;
+ } else {
+ ie->h.present |= UNI_BLLI_L2_Q933_P;
+ ie->l2_q933 = c & 0x3;
+ ie->l2_mode = (c >> 5) & 0x3;
+ if(!(c & 0x80)) {
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+ ie->h.present |= UNI_BLLI_L2_WSIZ_P;
+ ie->l2_wsiz = c & 0x7f;
+ if(!(c & 0x80))
+ goto rej;
+ }
+ }
+ }
+ break;
+
+ case UNI_BLLI_L3_ID:
+ ie->h.present |= UNI_BLLI_L3_P;
+ ie->l3 = c & 0x1f;
+ if(!(c & 0x80)) {
+ switch(ie->l3) {
+ default:
+ case UNI_BLLI_L3_CLMP:
+ case UNI_BLLI_L3_T70:
+ goto rej;
+
+ case UNI_BLLI_L3_X25:
+ case UNI_BLLI_L3_ISO8208:
+ case UNI_BLLI_L3_X223:
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+ ie->l3_mode = (c >> 5) & 0x3;
+ ie->h.present |= UNI_BLLI_L3_MODE_P;
+
+ if(c & 0x80)
+ break;
+
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+ ie->l3_psiz = c & 0xf;
+ ie->h.present |= UNI_BLLI_L3_PSIZ_P;
+
+ if(c & 0x80)
+ break;
+
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+ ie->l3_wsiz = c & 0x7f;
+ ie->h.present |= UNI_BLLI_L3_WSIZ_P;
+
+ if(!(c & 0x80))
+ goto rej;
+ break;
+
+ case UNI_BLLI_L3_TR9577:
+ if(ielen < 2)
+ goto rej;
+ ielen -= 2;
+ c = *msg->b_rptr++;
+ ie->l3_ipi = (c << 1) & 0xfe;
+ if(c & 0x80)
+ goto rej;
+ c = *msg->b_rptr++;
+ ie->l3_ipi |= c & 1;
+ if(!(c & 0x80))
+ goto rej;
+ ie->h.present |= UNI_BLLI_L3_IPI_P;
+
+ if(ie->l3_ipi != UNI_BLLI_L3_SNAP)
+ break;
+ if(ielen < 6)
+ goto rej;
+ ielen -= 6;
+ if(*msg->b_rptr++ != 0x80)
+ goto rej;
+ ie->h.present |= UNI_BLLI_L3_SNAP_P;
+ ie->oui = *msg->b_rptr++ << 16;
+ ie->oui |= *msg->b_rptr++ << 8;
+ ie->oui |= *msg->b_rptr++;
+ ie->pid = *msg->b_rptr++ << 8;
+ ie->pid |= *msg->b_rptr++;
+ break;
+
+ case UNI_BLLI_L3_H310:
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+ ie->l3_ttype = c & 0xf;
+ ie->l3_tcap = (c >> 4) & 0x7;
+ ie->h.present |= UNI_BLLI_L3_TTYPE_P;
+ if(c & 0x80)
+ break;
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+ ie->l3_fmux = (c >> 3) & 7;
+ ie->l3_bmux = c & 7;
+ ie->h.present |= UNI_BLLI_L3_MUX_P;
+ if(!(c & 0x80))
+ goto rej;
+ break;
+
+ case UNI_BLLI_L3_USER:
+ if(ielen == 0)
+ goto rej;
+ ielen--;
+ c = *msg->b_rptr++;
+ ie->l3_user = c & 0x7f;
+ ie->h.present |= UNI_BLLI_L3_USER_P;
+ if(!(c & 0x80))
+ goto rej;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ IE_END(BLLI);
+}
+
+/*********************************************************************
+ *
+ * Broadband locking shift
+ * Broadband non-locking shift.
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 41...42
+ * UNI4.0 pp. 9
+ *
+ * Procedure not supported in UNI4.0, but IE's must be recognized.
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, lshift)
+{
+ if(uni_print_iehdr("locking_shift", &ie->h, cx))
+ return;
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, lshift)
+{
+ UNUSED(cx); UNUSED(ie);
+ return -1;
+}
+
+DEF_IE_ENCODE(itu, lshift)
+{
+ START_IE(lshift, UNI_IE_LSHIFT, 1);
+ APP_BYTE(msg, 0x80 | ie->set);
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, lshift)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen != 1)
+ goto rej;
+
+ c = *msg->b_rptr++;
+
+ if(!(c & 0x80))
+ goto rej;
+ ie->set = c & 7;
+
+ IE_END(LSHIFT);
+}
+
+/***********************************************************************/
+
+DEF_IE_PRINT(itu, nlshift)
+{
+ if(uni_print_iehdr("nonlocking_shift", &ie->h, cx))
+ return;
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, nlshift)
+{
+ UNUSED(cx); UNUSED(ie);
+ return -1;
+}
+
+DEF_IE_ENCODE(itu, nlshift)
+{
+ START_IE(nlshift, UNI_IE_NLSHIFT, 1);
+ APP_BYTE(msg, 0x80 | ie->set);
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, nlshift)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen != 1)
+ goto rej;
+
+ c = *msg->b_rptr++;
+
+ if(!(c & 0x80))
+ goto rej;
+ ie->set = c & 7;
+
+ IE_END(NLSHIFT);
+}
+
+/*********************************************************************
+ *
+ * Broadband Sending Complete Indicator
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 74-75
+ *
+ * Only ITU-T coding allowed.
+ */
+DEF_IE_PRINT(itu, scompl)
+{
+ if(uni_print_iehdr("sending_complete", &ie->h, cx))
+ return;
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, scompl)
+{
+ UNUSED(ie); UNUSED(cx);
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, scompl)
+{
+ START_IE(scompl, UNI_IE_SCOMPL, 1);
+
+ APP_BYTE(msg, 0x80 | 0x21);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, scompl)
+{
+ IE_START(;);
+
+ if(ielen != 1)
+ goto rej;
+
+ if(*msg->b_rptr++ != (0x80 | 0x21))
+ goto rej;
+
+ IE_END(SCOMPL);
+}
+
+/*********************************************************************
+ *
+ * Broadband Repeat Indicator
+ *
+ * References for this IE are:
+ *
+ * Q.2931 p. 73
+ * PNNI1.0 p. 196
+ *
+ * Q.2931 has table 4-19. Only codepoints 0x2 and 0xa (for PNNI) supported.
+ *
+ * Only ITU-T coding allowed.
+ */
+DEF_IE_PRINT(itu, repeat)
+{
+ static const struct uni_print_tbl tbl[] = {
+ MKT(UNI_REPEAT_PRIDESC, desc),
+ MKT(UNI_REPEAT_STACK, stack),
+ EOT()
+ };
+
+ if(uni_print_iehdr("repeat", &ie->h, cx))
+ return;
+ uni_print_tbl("type", ie->type, tbl, cx);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, repeat)
+{
+ switch(ie->type) {
+
+ case UNI_REPEAT_PRIDESC:
+ break;
+
+ case UNI_REPEAT_STACK:
+ if(!cx->pnni)
+ return -1;
+ break;
+
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, repeat)
+{
+ START_IE(repeat, UNI_IE_REPEAT, 1);
+
+ APP_BYTE(msg, 0x80 | ie->type);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, repeat)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen != 1)
+ goto rej;
+
+ c = *msg->b_rptr++;
+ if(!(c & 0x80))
+ goto rej;
+ ie->type = c & 0xf;
+
+ IE_END(REPEAT);
+}
+
+/*********************************************************************
+ *
+ * Transit Network Selection
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 75...76
+ * UNI4.0 pp. 17
+ *
+ * According to UNI4.0 this is always National Network Id/Carried Id.
+ *
+ * ITU-T/Net coding allowed.
+ */
+
+DEF_IE_PRINT(itu, tns)
+{
+ u_int i;
+
+ if(uni_print_iehdr("tns", &ie->h, cx))
+ return;
+ uni_print_entry(cx, "net", "%u,\"", ie->len);
+ uni_putc('"', cx);
+ for(i = 0; i < ie->len; i++) {
+ if(ie->net[i] < ' ')
+ uni_printf(cx, "^%c", ie->net[i] + '@');
+ else if(ie->net[i] < '~')
+ uni_putc(ie->net[i], cx);
+ else
+ uni_printf(cx, "\\%03o", ie->net[i]);
+ }
+ uni_putc('"', cx);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, tns)
+{
+ u_int i;
+
+ UNUSED(cx);
+
+ if(ie->len == 0 || ie->len > UNI_TNS_MAXLEN)
+ return -1;
+ for(i = 0; i < ie->len; i++)
+ if(ie->net[i] < ' ' || ie->net[i] > '~')
+ return -1;
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, tns)
+{
+ START_IE(tns, UNI_IE_TNS, ie->len + 1);
+
+ APP_BYTE(msg, 0x80 | (0x2 << 4) | 0x1);
+ APP_BUF(msg, ie->net, ie->len);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, tns)
+{
+ IE_START(;);
+
+ if(ielen < 2 || ielen > 5)
+ goto rej;
+
+ if(*msg->b_rptr++ != (0x80 | (0x2 << 4) | 0x1))
+ goto rej;
+ ielen--;
+
+ ie->len = 0;
+ while(ielen--)
+ ie->net[ie->len++] = *msg->b_rptr++;
+
+ IE_END(TNS);
+}
+
+/*********************************************************************
+ *
+ * Restart indicator
+ *
+ * References for this IE are:
+ *
+ * Q.2931 pp. 73...74
+ * UNI4.0 p. 17
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, restart)
+{
+ static const struct uni_print_tbl tbl[] = {
+ MKT(UNI_RESTART_CHANNEL, channel),
+ MKT(UNI_RESTART_PATH, path),
+ MKT(UNI_RESTART_ALL, all),
+ EOT()
+ };
+
+ if(uni_print_iehdr("restart", &ie->h, cx))
+ return;
+ uni_print_tbl("class", ie->rclass, tbl, cx);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, restart)
+{
+ UNUSED(cx);
+
+ switch(ie->rclass) {
+ default:
+ return -1;
+
+ case UNI_RESTART_CHANNEL:
+ case UNI_RESTART_PATH:
+ case UNI_RESTART_ALL:
+ break;
+ }
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, restart)
+{
+ START_IE(restart, UNI_IE_RESTART, 1);
+
+ APP_BYTE(msg, 0x80 | ie->rclass);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, restart)
+{
+ u_char c;
+
+ IE_START(;);
+
+ if(ielen != 1)
+ goto rej;
+
+ ie->rclass = (c = *msg->b_rptr++) & 0x7;
+
+ if(!(c & 0x80))
+ goto rej;
+
+ IE_END(RESTART);
+}
+
+/*********************************************************************
+ *
+ * User-to-user info.
+ *
+ * References for this IE are:
+ *
+ * Q.2957
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, uu)
+{
+ u_int i;
+
+ if(uni_print_iehdr("uu", &ie->h, cx))
+ return;
+ uni_print_entry(cx, "len", "%u", ie->len);
+ uni_print_entry(cx, "info", "(");
+ for(i = 0; i < ie->len; i++)
+ uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->uu[i]);
+ uni_printf(cx, ")");
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, uu)
+{
+ UNUSED(cx);
+
+ if(ie->len > UNI_UU_MAXLEN)
+ return -1;
+
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, uu)
+{
+ START_IE(uu, UNI_IE_UU, ie->len);
+
+ APP_BUF(msg, ie->uu, ie->len);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, uu)
+{
+ IE_START(;);
+
+ if(ielen > UNI_UU_MAXLEN || ielen < 1)
+ goto rej;
+
+ ie->len = ielen;
+ ielen = 0;
+ (void)memcpy(ie->uu, msg->b_rptr, ie->len);
+ msg->b_rptr += ie->len;
+
+ IE_END(UU);
+}
+
+/*********************************************************************
+ *
+ * Generic Identifier Transport
+ *
+ * References for this IE are:
+ *
+ * UNI4.0 pp. 26...28
+ *
+ * UNI4.0 prescribes a fixed format for this IE. We have a flag in the
+ * context structur, which tells us whether the check of this IE should be
+ * hard or soft. Probably it should be hard for end systems and soft for
+ * network nodes.
+ *
+ * Only Net Coding allowed. (XXX)
+ */
+
+DEF_IE_PRINT(net, git)
+{
+ static const struct uni_print_tbl std_tbl[] = {
+ MKT(UNI_GIT_STD_DSMCC, dsmcc),
+ MKT(UNI_GIT_STD_H245, H.245),
+ EOT()
+ };
+ static const struct uni_print_tbl type_tbl[] = {
+ MKT(UNI_GIT_TYPE_SESS, sess),
+ MKT(UNI_GIT_TYPE_RES, res),
+ EOT()
+ };
+ u_int i, j;
+ char buf[20];
+
+ if(uni_print_iehdr("git", &ie->h, cx))
+ return;
+
+ uni_print_tbl("std", ie->std, std_tbl, cx);
+
+ uni_print_eol(cx);
+ uni_print_push_prefix("id", cx);
+ cx->indent++;
+ for(i = 0; i < ie->numsub; i++) {
+ sprintf(buf, "%u", i);
+ uni_print_entry(cx, buf, "(");
+ uni_print_tbl(NULL, ie->sub[i].type, type_tbl, cx);
+ for(j = 0; j < ie->sub[i].len; j++)
+ uni_printf(cx, ",0x%02x", ie->sub[i].val[j]);
+ uni_printf(cx, ")");
+ uni_print_eol(cx);
+ }
+ cx->indent--;
+ uni_print_pop_prefix(cx);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, git)
+{
+ u_int i;
+
+ if(cx->git_hard) {
+ switch(ie->std) {
+ case UNI_GIT_STD_DSMCC:
+ case UNI_GIT_STD_H245:
+ break;
+ default:
+ return -1;
+ }
+ if(ie->numsub != 2)
+ return -1;
+ if(ie->sub[0].type != UNI_GIT_TYPE_SESS)
+ return -1;
+ if(ie->sub[0].len > UNI_GIT_MAXSESS)
+ return -1;
+ if(ie->sub[1].type != UNI_GIT_TYPE_RES)
+ return -1;
+ if(ie->sub[1].len > UNI_GIT_MAXRES)
+ return -1;
+ } else {
+ if(ie->numsub > UNI_GIT_MAXSUB)
+ return -1;
+ for(i = 0; i < ie->numsub; i++)
+ if(ie->sub[i].len > UNI_GIT_MAXVAL)
+ return -1;
+ }
+ return 0;
+}
+
+DEF_IE_ENCODE(net, git)
+{
+ u_int i;
+
+ START_IE(git, UNI_IE_GIT, 1 + ie->numsub * (1 + UNI_GIT_MAXVAL));
+
+ APP_BYTE(msg, ie->std);
+ for(i = 0; i < ie->numsub; i++) {
+ APP_BYTE(msg, ie->sub[i].type);
+ APP_BYTE(msg, ie->sub[i].len);
+ APP_BUF(msg, ie->sub[i].val, ie->sub[i].len);
+ }
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(net, git)
+{
+ IE_START(;);
+
+ if(ielen > 1 + UNI_GIT_MAXSUB * (1 + UNI_GIT_MAXVAL) || ielen < 1)
+ goto rej;
+
+ ie->std = *msg->b_rptr++;
+ ielen--;
+
+ ie->numsub = 0;
+ while(ielen > 0) {
+ if(ie->numsub >= UNI_GIT_MAXSUB)
+ goto rej;
+
+ ie->sub[ie->numsub].type = *msg->b_rptr++;
+ ielen--;
+
+ if(ielen == 0)
+ goto rej;
+ ie->sub[ie->numsub].len = *msg->b_rptr++;
+ ielen--;
+
+ if(ie->sub[ie->numsub].len > UNI_GIT_MAXVAL)
+ goto rej;
+ if(ie->sub[ie->numsub].len > (u_int)ielen)
+ goto rej;
+
+ (void)memcpy(ie->sub[ie->numsub].val, msg->b_rptr, ie->sub[ie->numsub].len);
+ ielen -= ie->sub[ie->numsub].len;
+ msg->b_rptr += ie->sub[ie->numsub].len;
+
+ ie->numsub++;
+ }
+
+ IE_END(GIT);
+}
+
+/*********************************************************************
+ *
+ * Additional ABR Parameters
+ * ABR Setup parameters
+ *
+ * References for this IE are:
+ *
+ * UNI4.0 pp. 78...82
+ * PNNI1.0 p. 195
+ *
+ * Notes:
+ * Only NET coding.
+ */
+
+static void
+print_abr_rec(struct unicx *cx, struct uni_abr_rec *rec)
+{
+ if(rec->present & UNI_ABR_REC_NRM_P)
+ uni_print_entry(cx, "nrm", "%d", rec->nrm);
+ if(rec->present & UNI_ABR_REC_TRM_P)
+ uni_print_entry(cx, "trm", "%d", rec->trm);
+ if(rec->present & UNI_ABR_REC_CDF_P)
+ uni_print_entry(cx, "cdf", "%d", rec->cdf);
+ if(rec->present & UNI_ABR_REC_ADTF_P)
+ uni_print_entry(cx, "adtf", "%d", rec->adtf);
+}
+
+DEF_IE_PRINT(net, abradd)
+{
+ if(uni_print_iehdr("abradd", &ie->h, cx))
+ return;
+
+ uni_print_push_prefix("fwd", cx);
+ print_abr_rec(cx, &ie->fwd);
+ uni_print_pop_prefix(cx);
+
+ uni_print_push_prefix("bwd", cx);
+ print_abr_rec(cx, &ie->bwd);
+ uni_print_pop_prefix(cx);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, abradd)
+{
+ UNUSED(cx);
+ UNUSED(ie);
+
+ return 0;
+}
+
+static u_int
+encode_abr_rec(struct uni_abr_rec *rec)
+{
+ u_int ret = rec->present & 0xf000;
+
+ if(ret & UNI_ABR_REC_NRM_P)
+ ret |= (rec->nrm & 0x7) << 25;
+ if(ret & UNI_ABR_REC_TRM_P)
+ ret |= (rec->trm & 0x7) << 22;
+ if(ret & UNI_ABR_REC_CDF_P)
+ ret |= (rec->cdf & 0x7) << 19;
+ if(ret & UNI_ABR_REC_ADTF_P)
+ ret |= (rec->adtf & 0x3ff) << 9;
+
+ return ret;
+}
+
+DEF_IE_ENCODE(net, abradd)
+{
+ START_IE(abradd, UNI_IE_ABRADD, 10);
+
+ APP_SUB_32BIT(msg, UNI_ABRADD_FADD_ID, encode_abr_rec(&ie->fwd));
+ APP_SUB_32BIT(msg, UNI_ABRADD_BADD_ID, encode_abr_rec(&ie->bwd));
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+static int
+decode_abr_rec(struct uni_msg *msg, struct uni_abr_rec *rec)
+{
+ u_int val;
+
+ val = *msg->b_rptr++ << 24;
+ val |= *msg->b_rptr++ << 16;
+ val |= *msg->b_rptr++ << 8;
+ val |= *msg->b_rptr++ << 0;
+
+ rec->present = val & 0xf000;
+
+ rec->nrm = (val & UNI_ABR_REC_NRM_P) ? ((val >> 25) & 0x7) : 0;
+ rec->trm = (val & UNI_ABR_REC_TRM_P) ? ((val >> 22) & 0x7) : 0;
+ rec->cdf = (val & UNI_ABR_REC_CDF_P) ? ((val >> 19) & 0x7) : 0;
+ rec->adtf = (val & UNI_ABR_REC_ADTF_P)? ((val >> 9) & 0x3ff) : 0;
+
+ return 0;
+}
+
+DEF_IE_DECODE(net, abradd)
+{
+ IE_START(;);
+
+ if(ielen != 10)
+ goto rej;
+
+
+ while(ielen--) {
+ switch(*msg->b_rptr++) {
+
+ default:
+ goto rej;
+
+ case UNI_ABRADD_FADD_ID:
+ if(decode_abr_rec(msg, &ie->fwd))
+ goto rej;
+ ielen -= 4;
+ break;
+
+ case UNI_ABRADD_BADD_ID:
+ if(decode_abr_rec(msg, &ie->bwd))
+ goto rej;
+ ielen -= 4;
+ break;
+ }
+ }
+ IE_END(ABRADD);
+}
+
+/*********************************************************************/
+
+DEF_IE_PRINT(net, abrsetup)
+{
+ if(uni_print_iehdr("abrsetup", &ie->h, cx))
+ return;
+
+ uni_print_entry(cx, "rm_frt", "%d", ie->rmfrt);
+
+ uni_print_push_prefix("fwd", cx);
+ if(ie->h.present & UNI_ABRSETUP_FICR_P)
+ uni_print_entry(cx, "icr", "%d", ie->ficr);
+ if(ie->h.present & UNI_ABRSETUP_FTBE_P)
+ uni_print_entry(cx, "tbe", "%d", ie->ftbe);
+ if(ie->h.present & UNI_ABRSETUP_FRIF_P)
+ uni_print_entry(cx, "rif", "%d", ie->frif);
+ if(ie->h.present & UNI_ABRSETUP_FRDF_P)
+ uni_print_entry(cx, "rdf", "%d", ie->frdf);
+ uni_print_pop_prefix(cx);
+
+ uni_print_push_prefix("bwd", cx);
+ if(ie->h.present & UNI_ABRSETUP_BICR_P)
+ uni_print_entry(cx, "icr", "%d", ie->bicr);
+ if(ie->h.present & UNI_ABRSETUP_BTBE_P)
+ uni_print_entry(cx, "tbe", "%d", ie->btbe);
+ if(ie->h.present & UNI_ABRSETUP_BRIF_P)
+ uni_print_entry(cx, "rif", "%d", ie->brif);
+ if(ie->h.present & UNI_ABRSETUP_BRDF_P)
+ uni_print_entry(cx, "rdf", "%d", ie->brdf);
+ uni_print_pop_prefix(cx);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, abrsetup)
+{
+ if(cx->pnni) {
+ if(!(ie->h.present & UNI_ABRSETUP_FICR_P))
+ return -1;
+ if(!(ie->h.present & UNI_ABRSETUP_BICR_P))
+ return -1;
+ if(!(ie->h.present & UNI_ABRSETUP_FTBE_P))
+ return -1;
+ if(!(ie->h.present & UNI_ABRSETUP_BTBE_P))
+ return -1;
+ if(!(ie->h.present & UNI_ABRSETUP_FRIF_P))
+ return -1;
+ if(!(ie->h.present & UNI_ABRSETUP_BRIF_P))
+ return -1;
+ if(!(ie->h.present & UNI_ABRSETUP_FRDF_P))
+ return -1;
+ if(!(ie->h.present & UNI_ABRSETUP_BRDF_P))
+ return -1;
+ if(!(ie->h.present & UNI_ABRSETUP_RMFRT_P))
+ return -1;
+ }
+
+ if(!(ie->h.present & UNI_ABRSETUP_RMFRT_P))
+ return -1;
+
+ if(ie->h.present & UNI_ABRSETUP_FICR_P)
+ if(ie->ficr >= 1 << 24)
+ return -1;
+ if(ie->h.present & UNI_ABRSETUP_BICR_P)
+ if(ie->bicr >= 1 << 24)
+ return -1;
+
+ if(ie->h.present & UNI_ABRSETUP_FTBE_P)
+ if(ie->ftbe >= 1 << 24 || ie->ftbe == 0)
+ return -1;
+ if(ie->h.present & UNI_ABRSETUP_BTBE_P)
+ if(ie->btbe >= 1 << 24 || ie->btbe == 0)
+ return -1;
+
+ if(ie->rmfrt >= 1 << 24)
+ return -1;
+
+ if(ie->h.present & UNI_ABRSETUP_FRIF_P)
+ if(ie->frif > 15)
+ return -1;
+ if(ie->h.present & UNI_ABRSETUP_FRDF_P)
+ if(ie->frdf > 15)
+ return -1;
+ if(ie->h.present & UNI_ABRSETUP_BRIF_P)
+ if(ie->brif > 15)
+ return -1;
+ if(ie->h.present & UNI_ABRSETUP_BRDF_P)
+ if(ie->brdf > 15)
+ return -1;
+ return 0;
+}
+
+DEF_IE_ENCODE(net, abrsetup)
+{
+ START_IE(abrsetup, UNI_IE_ABRSETUP, 32);
+
+ APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_FICR_P,
+ UNI_ABRSETUP_FICR_ID, ie->ficr);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_BICR_P,
+ UNI_ABRSETUP_BICR_ID, ie->bicr);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_FTBE_P,
+ UNI_ABRSETUP_FTBE_ID, ie->ftbe);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_BTBE_P,
+ UNI_ABRSETUP_BTBE_ID, ie->btbe);
+ APP_SUB_24BIT(msg, UNI_ABRSETUP_RMFRT_ID, ie->rmfrt);
+ APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_FRIF_P,
+ UNI_ABRSETUP_FRIF_ID, ie->frif);
+ APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_BRIF_P,
+ UNI_ABRSETUP_BRIF_ID, ie->brif);
+ APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_FRDF_P,
+ UNI_ABRSETUP_FRDF_ID, ie->frdf);
+ APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_BRDF_P,
+ UNI_ABRSETUP_BRDF_ID, ie->brdf);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(net, abrsetup)
+{
+ IE_START(;);
+
+ if(ielen < 4 || ielen > 32)
+ goto rej;
+
+
+ while(ielen--) {
+ switch(*msg->b_rptr++) {
+
+ default:
+ goto rej;
+
+
+ DEC_GETF3(ABRSETUP_FICR, ficr, ie->h.present);
+ DEC_GETF3(ABRSETUP_BICR, bicr, ie->h.present);
+ DEC_GETF3(ABRSETUP_FTBE, ftbe, ie->h.present);
+ DEC_GETF3(ABRSETUP_BTBE, btbe, ie->h.present);
+ DEC_GETF1(ABRSETUP_FRIF, frif, ie->h.present);
+ DEC_GETF1(ABRSETUP_BRIF, brif, ie->h.present);
+ DEC_GETF1(ABRSETUP_FRDF, frdf, ie->h.present);
+ DEC_GETF1(ABRSETUP_BRDF, brdf, ie->h.present);
+ DEC_GETF3(ABRSETUP_RMFRT, frif, ie->h.present);
+ }
+ }
+ IE_END(ABRSETUP);
+}
+
+/*********************************************************************
+ *
+ * Broadband report type
+ *
+ * References for this IE are:
+ *
+ * Q.2963.1 pp. 7...8
+ *
+ * Only ITU-T coding allowed.
+ */
+
+DEF_IE_PRINT(itu, report)
+{
+ static const struct uni_print_tbl tbl[] = {
+ MKT(UNI_REPORT_MODCONF, modconf),
+ MKT(UNI_REPORT_CLOCK, clock),
+ MKT(UNI_REPORT_EEAVAIL, eeavail),
+ MKT(UNI_REPORT_EEREQ, eereq),
+ MKT(UNI_REPORT_EECOMPL, eecompl),
+ EOT()
+ };
+
+ if(uni_print_iehdr("report", &ie->h, cx))
+ return;
+ uni_print_tbl("type", ie->report, tbl, cx);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, report)
+{
+ UNUSED(cx);
+
+ switch(ie->report) {
+
+ default:
+ return -1;
+
+ case UNI_REPORT_MODCONF:
+ case UNI_REPORT_CLOCK:
+ case UNI_REPORT_EEAVAIL:
+ case UNI_REPORT_EEREQ:
+ case UNI_REPORT_EECOMPL:
+ break;
+ }
+ return 0;
+}
+
+DEF_IE_ENCODE(itu, report)
+{
+ START_IE(report, UNI_IE_REPORT, 1);
+
+ APP_BYTE(msg, ie->report);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(itu, report)
+{
+ IE_START(;);
+ if(ielen != 1)
+ goto rej;
+
+ ie->report = *msg->b_rptr++;
+
+ IE_END(REPORT);
+}
+
+/*********************************************************************
+ *
+ * Soft PVPC/PVCC
+ *
+ * References for this IE are:
+ *
+ * PNNI1.0 pp. 201...203
+ *
+ * Only NET coding allowed.
+ */
+DEF_IE_PRINT(net, calling_soft)
+{
+ if(uni_print_iehdr("calling_soft", &ie->h, cx))
+ return;
+
+ uni_print_entry(cx, "vpi", "%d", ie->vpi);
+ if(ie->h.present & UNI_CALLING_SOFT_VCI_P)
+ uni_print_entry(cx, "vci", "%d", ie->vci);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_PRINT(net, called_soft)
+{
+ static const struct uni_print_tbl tab[] = {
+ MKT(UNI_SOFT_SEL_ANY, any),
+ MKT(UNI_SOFT_SEL_REQ, required),
+ MKT(UNI_SOFT_SEL_ASS, assigned),
+ EOT()
+ };
+
+ if(uni_print_iehdr("called_soft", &ie->h, cx))
+ return;
+
+ uni_print_tbl("selection", ie->sel, tab, cx);
+ if(ie->h.present & UNI_CALLED_SOFT_VPI_P)
+ uni_print_entry(cx, "vpi", "%d", ie->vpi);
+ if(ie->h.present & UNI_CALLED_SOFT_VCI_P)
+ uni_print_entry(cx, "vci", "%d", ie->vci);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, calling_soft)
+{
+ UNUSED(cx);
+
+ if(ie->vpi >= 1 << 12)
+ return -1;
+ return 0;
+}
+
+DEF_IE_CHECK(net, called_soft)
+{
+ UNUSED(cx);
+
+ switch(ie->sel) {
+
+ case UNI_SOFT_SEL_ANY:
+ case UNI_SOFT_SEL_REQ:
+ case UNI_SOFT_SEL_ASS:
+ break;
+
+ default:
+ return -1;
+ }
+ if(ie->h.present & UNI_CALLED_SOFT_VPI_P) {
+ if(ie->vpi >= 1 << 12)
+ return -1;
+ } else {
+ if(ie->sel != UNI_SOFT_SEL_ANY)
+ return -1;
+ }
+
+ if(ie->h.present & UNI_CALLED_SOFT_VCI_P)
+ if(!(ie->h.present & UNI_CALLED_SOFT_VPI_P))
+ return -1;
+
+
+ return 0;
+}
+
+DEF_IE_ENCODE(net, calling_soft)
+{
+ START_IE(calling_soft, UNI_IE_CALLING_SOFT, 6);
+
+ APP_BYTE(msg, 0x81);
+ APP_16BIT(msg, ie->vpi);
+
+ if(ie->h.present & UNI_CALLING_SOFT_VCI_P) {
+ APP_BYTE(msg, 0x82);
+ APP_16BIT(msg, ie->vci);
+ }
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_ENCODE(net, called_soft)
+{
+ START_IE(called_soft, UNI_IE_CALLED_SOFT, 7);
+
+ APP_BYTE(msg, ie->sel);
+
+ if(ie->h.present & UNI_CALLED_SOFT_VPI_P) {
+ APP_BYTE(msg, 0x81);
+ APP_16BIT(msg, ie->vpi);
+ }
+
+ if(ie->h.present & UNI_CALLED_SOFT_VCI_P) {
+ APP_BYTE(msg, 0x82);
+ APP_16BIT(msg, ie->vci);
+ }
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(net, calling_soft)
+{
+ int vci_seen, vpi_seen;
+
+ IE_START(;);
+ if(ielen < 3)
+ goto rej;
+
+ vci_seen = 0;
+ vpi_seen = 0;
+
+ while(ielen) {
+ switch(*msg->b_rptr++) {
+
+ case 0x81:
+ if(!vpi_seen) {
+ ie->vpi = *msg->b_rptr++ << 8;
+ ie->vpi |= *msg->b_rptr++;
+ } else {
+ msg->b_rptr += 2;
+ }
+ ielen -= 3;
+ break;
+
+ case 0x82:
+ if(!vci_seen) {
+ ie->vci = *msg->b_rptr++ << 8;
+ ie->vci |= *msg->b_rptr++;
+ } else {
+ msg->b_rptr += 2;
+ }
+ ie->h.present |= UNI_CALLING_SOFT_VCI_P;
+ ielen -= 3;
+ break;
+
+ default:
+ goto rej;
+ }
+ }
+
+ if(!vpi_seen)
+ goto rej;
+
+ IE_END(CALLING_SOFT);
+}
+
+DEF_IE_DECODE(net, called_soft)
+{
+ int vci_seen, vpi_seen;
+
+ IE_START(;);
+ if(ielen < 3)
+ goto rej;
+
+ vci_seen = 0;
+ vpi_seen = 0;
+
+ while(ielen) {
+ switch(*msg->b_rptr++) {
+
+ case 0x81:
+ if(!vpi_seen) {
+ ie->vpi = *msg->b_rptr++ << 8;
+ ie->vpi |= *msg->b_rptr++;
+ vpi_seen = 1;
+ } else {
+ msg->b_rptr += 2;
+ }
+ ielen -= 3;
+ ie->h.present |= UNI_CALLED_SOFT_VCI_P;
+ break;
+
+ case 0x82:
+ if(!vci_seen) {
+ ie->vci = *msg->b_rptr++ << 8;
+ ie->vci |= *msg->b_rptr++;
+ vci_seen = 1;
+ } else {
+ msg->b_rptr += 2;
+ }
+ ie->h.present |= UNI_CALLED_SOFT_VCI_P;
+ ielen -= 3;
+ break;
+
+ default:
+ goto rej;
+ }
+ }
+
+ IE_END(CALLED_SOFT);
+}
+
+/*********************************************************************
+ *
+ * Crankback
+ *
+ * References for this IE are:
+ *
+ * PNNI1.0 pp. 203...206
+ *
+ * Only NET coding allowed.
+ */
+
+DEF_IE_PRINT(net, crankback)
+{
+ u_int j;
+
+ if(uni_print_iehdr("crankback", &ie->h, cx))
+ return;
+
+ uni_print_entry(cx, "level", "%d", ie->level);
+
+ switch(ie->type) {
+
+ case UNI_CRANKBACK_IF:
+ uni_print_entry(cx, "type", "interface");
+ break;
+
+ case UNI_CRANKBACK_NODE:
+ uni_print_entry(cx, "type", "node");
+ uni_print_entry(cx, "node", "{%d/", ie->id.node.level);
+ for(j = 0; j < 21; j++)
+ uni_printf(cx, "%02x", ie->id.node.id[j]);
+ uni_printf(cx, "}");
+ uni_print_eol(cx);
+ break;
+
+ case UNI_CRANKBACK_LINK:
+ uni_print_entry(cx, "type", "link");
+ uni_print_push_prefix("link", cx);
+ cx->indent++;
+
+ uni_print_entry(cx, "prec", "{%d/", ie->id.link.plevel);
+ for(j = 0; j < 21; j++)
+ uni_printf(cx, "%02x", ie->id.link.pid[j]);
+ uni_printf(cx, "}");
+ uni_print_eol(cx);
+
+ uni_print_entry(cx, "port", "0x%04x", ie->id.link.port);
+ uni_print_eol(cx);
+
+ uni_print_entry(cx, "succ", "{%d/", ie->id.link.slevel);
+ for(j = 0; j < 21; j++)
+ uni_printf(cx, "%02x", ie->id.link.sid[j]);
+ uni_printf(cx, "}");
+ uni_print_eol(cx);
+
+ cx->indent--;
+ uni_print_pop_prefix(cx);
+ break;
+
+ default:
+ uni_print_entry(cx, "type", "0x%02x", ie->type);
+ break;
+ }
+
+ uni_print_entry(cx, "cause", "0x%02x", ie->cause);
+
+ if(ie->h.present & UNI_CRANKBACK_TOP_P) {
+ uni_print_push_prefix("topol", cx);
+ uni_print_entry(cx, "dir", "%d", ie->diag.top.dir);
+ uni_print_entry(cx, "port", "0x%04x", ie->diag.top.port);
+ uni_print_entry(cx, "avcr", "%u", ie->diag.top.avcr);
+ if(ie->h.present & UNI_CRANKBACK_TOPX_P) {
+ uni_print_entry(cx, "crm", "%u", ie->diag.top.crm);
+ uni_print_entry(cx, "vf", "%u", ie->diag.top.vf);
+ }
+ uni_print_pop_prefix(cx);
+ uni_print_eol(cx);
+ }
+ if(ie->h.present & UNI_CRANKBACK_QOS_P) {
+ uni_print_push_prefix("qos", cx);
+ uni_print_entry(cx, "ctd", "%savail", ie->diag.qos.ctd ? "" : "un");
+ uni_print_entry(cx, "cdv", "%savail", ie->diag.qos.cdv ? "" : "un");
+ uni_print_entry(cx, "clr", "%savail", ie->diag.qos.clr ? "" : "un");
+ uni_print_entry(cx, "other", "%savail", ie->diag.qos.other ? "" : "un");
+ uni_print_pop_prefix(cx);
+ uni_print_eol(cx);
+ }
+
+ uni_print_eol(cx);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, crankback)
+{
+ UNUSED(cx);
+
+ if(ie->level > 104)
+ return -1;
+ switch(ie->type) {
+ case UNI_CRANKBACK_IF:
+ break;
+ case UNI_CRANKBACK_NODE:
+ if(ie->id.node.level > 104)
+ return -1;
+ break;
+
+ case UNI_CRANKBACK_LINK:
+ if(ie->id.link.plevel > 104)
+ return -1;
+ if(ie->id.link.slevel > 104)
+ return -1;
+ break;
+
+ default:
+ return -1;
+ }
+
+ if(ie->h.present & UNI_CRANKBACK_TOP_P) {
+ if(ie->h.present & UNI_CRANKBACK_QOS_P)
+ return -1;
+
+ if(ie->cause != UNI_CAUSE_CRATE_NAVL)
+ return -1;
+ switch(ie->diag.top.dir) {
+
+ case 0x00:
+ case 0x01:
+ break;
+
+ default:
+ return -1;
+ }
+ }
+ if(ie->h.present & UNI_CRANKBACK_QOS_P) {
+ if(ie->cause != UNI_CAUSE_QOS_NAVL)
+ return -1;
+ }
+ return 0;
+}
+
+DEF_IE_ENCODE(net, crankback)
+{
+ START_IE(crankback, UNI_IE_CRANKBACK, 72);
+
+ APP_BYTE(msg, ie->level);
+ APP_BYTE(msg, ie->type);
+
+ switch(ie->type) {
+
+ case UNI_CRANKBACK_IF:
+ break;
+
+ case UNI_CRANKBACK_NODE:
+ APP_BYTE(msg, ie->id.node.level);
+ APP_BUF(msg, ie->id.node.id, 21);
+ break;
+
+ case UNI_CRANKBACK_LINK:
+ APP_BYTE(msg, ie->id.link.plevel);
+ APP_BUF(msg, ie->id.link.pid, 21);
+ APP_32BIT(msg, ie->id.link.port);
+ APP_BYTE(msg, ie->id.link.slevel);
+ APP_BUF(msg, ie->id.link.sid, 21);
+ break;
+ }
+
+ APP_BYTE(msg, ie->cause);
+
+ if(ie->h.present & UNI_CRANKBACK_TOP_P) {
+ APP_BYTE(msg, ie->diag.top.dir);
+ APP_32BIT(msg, ie->diag.top.port);
+ APP_32BIT(msg, ie->diag.top.avcr);
+ if(ie->h.present & UNI_CRANKBACK_TOPX_P) {
+ APP_32BIT(msg, ie->diag.top.crm);
+ APP_32BIT(msg, ie->diag.top.vf);
+ }
+ }
+
+ if(ie->h.present & UNI_CRANKBACK_QOS_P) {
+ APP_BYTE(msg, (ie->diag.qos.ctd << 3)
+ |(ie->diag.qos.cdv << 2)
+ |(ie->diag.qos.clr << 1)
+ |(ie->diag.qos.other));
+ }
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+
+DEF_IE_DECODE(net, crankback)
+{
+ IE_START(;);
+
+ if(ielen < 3)
+ goto rej;
+
+ ie->level = *msg->b_rptr++;
+ ielen--;
+
+ ie->type = *msg->b_rptr++;
+ ielen--;
+
+ switch(ie->type) {
+
+ default:
+ goto rej;
+
+ case UNI_CRANKBACK_IF:
+ break;
+
+ case UNI_CRANKBACK_NODE:
+ if(ielen < 22)
+ goto rej;
+ ie->id.node.level = *msg->b_rptr++;
+ (void)memcpy(ie->id.node.id, msg->b_rptr, 21);
+ msg->b_rptr += 21;
+ ielen -= 22;
+ break;
+
+ case UNI_CRANKBACK_LINK:
+ if(ielen < 48)
+ goto rej;
+ ie->id.link.plevel = *msg->b_rptr++;
+ (void)memcpy(ie->id.link.pid, msg->b_rptr, 21);
+ msg->b_rptr += 21;
+ ielen -= 22;
+
+ ie->id.link.port = *msg->b_rptr++ << 24;
+ ie->id.link.port |= *msg->b_rptr++ << 16;
+ ie->id.link.port |= *msg->b_rptr++ << 8;
+ ie->id.link.port |= *msg->b_rptr++ << 0;
+ ielen -= 4;
+
+ ie->id.link.slevel = *msg->b_rptr++;
+ (void)memcpy(ie->id.link.sid, msg->b_rptr, 21);
+ msg->b_rptr += 21;
+ ielen -= 22;
+
+ break;
+ }
+
+ if(ielen < 1)
+ goto rej;
+ ie->cause = *msg->b_rptr++;
+ ielen--;
+
+ if(ie->cause == UNI_CAUSE_CRATE_NAVL) {
+ if(ielen > 0) {
+ if(ielen != 9 && ielen != 17)
+ goto rej;
+ ie->diag.top.dir = *msg->b_rptr++;
+ ie->diag.top.port = *msg->b_rptr++ << 24;
+ ie->diag.top.port |= *msg->b_rptr++ << 16;
+ ie->diag.top.port |= *msg->b_rptr++ << 8;
+ ie->diag.top.port |= *msg->b_rptr++ << 0;
+ ie->diag.top.avcr = *msg->b_rptr++ << 24;
+ ie->diag.top.avcr |= *msg->b_rptr++ << 16;
+ ie->diag.top.avcr |= *msg->b_rptr++ << 8;
+ ie->diag.top.avcr |= *msg->b_rptr++ << 0;
+ ielen -= 9;
+ ie->h.present |= UNI_CRANKBACK_TOP_P;
+ if(ielen > 0) {
+ ie->diag.top.crm = *msg->b_rptr++ << 24;
+ ie->diag.top.crm |= *msg->b_rptr++ << 16;
+ ie->diag.top.crm |= *msg->b_rptr++ << 8;
+ ie->diag.top.crm |= *msg->b_rptr++ << 0;
+ ie->diag.top.vf = *msg->b_rptr++ << 24;
+ ie->diag.top.vf |= *msg->b_rptr++ << 16;
+ ie->diag.top.vf |= *msg->b_rptr++ << 8;
+ ie->diag.top.vf |= *msg->b_rptr++ << 0;
+ ie->h.present |= UNI_CRANKBACK_TOPX_P;
+ ielen -= 8;
+ }
+ }
+ } else if(ie->cause == UNI_CAUSE_QOS_NAVL) {
+ if(ielen > 0) {
+ if(ielen != 1)
+ goto rej;
+ ie->diag.qos.ctd = *msg->b_rptr >> 3;
+ ie->diag.qos.cdv = *msg->b_rptr >> 2;
+ ie->diag.qos.clr = *msg->b_rptr >> 1;
+ ie->diag.qos.other = *msg->b_rptr >> 0;
+ ie->h.present |= UNI_CRANKBACK_QOS_P;
+ ielen -= 1;
+ }
+ } else {
+ if(ielen > 0)
+ goto rej;
+ }
+
+ IE_END(CRANKBACK);
+}
+
+/*********************************************************************
+ *
+ * Designated transit list
+ *
+ * References for this IE are:
+ *
+ * PNNI1.0 pp. 206...208
+ *
+ * Only NET coding allowed.
+ */
+DEF_IE_PRINT(net, dtl)
+{
+ u_int i, j;
+ char buf[10];
+
+ if(uni_print_iehdr("dtl", &ie->h, cx))
+ return;
+
+ uni_print_entry(cx, "ptr", "%d(%d)", ie->ptr, ie->ptr / UNI_DTL_LOGNP_SIZE);
+ uni_print_push_prefix("dtl", cx);
+ cx->indent++;
+ uni_printf(cx, "{");
+ for(i = 0; i < ie->num; i++) {
+ sprintf(buf, "%d", i);
+ uni_print_entry(cx, buf, "{%d/", ie->dtl[i].node_level);
+ for(j = 0; j < 21; j++)
+ uni_printf(cx, "%02x", ie->dtl[i].node_id[j]);
+ uni_printf(cx, ",%04x}", ie->dtl[i].port_id);
+ uni_print_eol(cx);
+ }
+ cx->indent--;
+ uni_print_pop_prefix(cx);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, dtl)
+{
+ u_int i;
+
+ UNUSED(cx);
+
+ if(ie->ptr % UNI_DTL_LOGNP_SIZE != 0)
+ return -1;
+ if(ie->ptr / UNI_DTL_LOGNP_SIZE > UNI_DTL_MAXNUM)
+ return -1;
+ if(ie->num > UNI_DTL_MAXNUM)
+ return -1;
+ for(i = 0; i < ie->num; i++)
+ if(ie->dtl[i].node_level > 104)
+ return -1;
+ return 0;
+}
+
+DEF_IE_ENCODE(net, dtl)
+{
+ u_int i;
+
+ START_IE(dtl, UNI_IE_DTL, 2 + UNI_DTL_LOGNP_SIZE * ie->num);
+
+ APP_16BIT(msg, ie->ptr);
+
+ for(i = 0; i < ie->num; i++) {
+ APP_BYTE(msg, UNI_DTL_LOGNP);
+ APP_BYTE(msg, ie->dtl[i].node_level);
+ APP_BUF(msg, ie->dtl[i].node_id, 21);
+ APP_32BIT(msg, ie->dtl[i].port_id);
+ }
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+
+DEF_IE_DECODE(net, dtl)
+{
+ IE_START(;);
+
+ if(ielen < 2)
+ goto rej;
+
+ ie->ptr = *msg->b_rptr++ << 8;
+ ie->ptr |= *msg->b_rptr++;
+ ielen -= 2;
+
+ if(ielen % UNI_DTL_LOGNP_SIZE != 0)
+ goto rej;
+ if(ielen / UNI_DTL_LOGNP_SIZE > UNI_DTL_MAXNUM)
+ goto rej;
+
+ ie->num = 0;
+ while(ielen) {
+ if(*msg->b_rptr++ != UNI_DTL_LOGNP)
+ goto rej;
+ ielen--;
+
+ ie->dtl[ie->num].node_level = *msg->b_rptr++;
+ ielen--;
+
+ (void)memcpy(ie->dtl[ie->num].node_id, msg->b_rptr, 21);
+ msg->b_rptr += 21;
+ ielen -= 21;
+
+ ie->dtl[ie->num].port_id = *msg->b_rptr++ << 24;
+ ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 16;
+ ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 8;
+ ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 0;
+ ielen -= 4;
+
+ ie->num++;
+ }
+
+ IE_END(DTL);
+}
+
+/*********************************************************************
+ *
+ * Leaf initiated join call identifier.
+ * Leaf initiated join parameters.
+ * Leaf initiated join sequence number.
+ *
+ * References for this IE are:
+ *
+ * UNI4.0 pp. 46...48
+ *
+ * Only NET coding allowed.
+ */
+
+/**********************************************************************/
+
+DEF_IE_PRINT(net, lij_callid)
+{
+ static const struct uni_print_tbl type_tbl[] = {
+ MKT(UNI_LIJ_IDTYPE_ROOT, root),
+ EOT()
+ };
+
+ if(uni_print_iehdr("lij_callid", &ie->h, cx))
+ return;
+
+ uni_print_tbl("type", ie->type, type_tbl, cx);
+ uni_print_entry(cx, "id", "0x%x", ie->callid);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, lij_callid)
+{
+ UNUSED(cx);
+
+ switch(ie->type) {
+
+ case UNI_LIJ_IDTYPE_ROOT:
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+DEF_IE_ENCODE(net, lij_callid)
+{
+ START_IE(lij_callid, UNI_IE_LIJ_CALLID, 5);
+
+ APP_BYTE(msg, 0x80 | ie->type);
+ APP_32BIT(msg, ie->callid);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(net, lij_callid)
+{
+ IE_START(;);
+
+ if(ielen != 5)
+ goto rej;
+
+ ie->type = *msg->b_rptr++ & 0xf;
+ ie->callid = *msg->b_rptr++ << 24;
+ ie->callid |= *msg->b_rptr++ << 16;
+ ie->callid |= *msg->b_rptr++ << 8;
+ ie->callid |= *msg->b_rptr++ << 0;
+
+ IE_END(LIJ_CALLID);
+}
+
+/**********************************************************************/
+
+DEF_IE_PRINT(net, lij_param)
+{
+ static const struct uni_print_tbl lscreen_tbl[] = {
+ MKT(UNI_LIJ_SCREEN_NETJOIN, netjoin),
+ EOT()
+ };
+
+ if(uni_print_iehdr("lij_param", &ie->h, cx))
+ return;
+ uni_print_tbl("screen", ie->screen, lscreen_tbl, cx);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, lij_param)
+{
+ UNUSED(cx);
+
+ switch(ie->screen) {
+
+ case UNI_LIJ_SCREEN_NETJOIN:
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+DEF_IE_ENCODE(net, lij_param)
+{
+ START_IE(lij_param, UNI_IE_LIJ_PARAM, 1);
+
+ APP_BYTE(msg, 0x80 | ie->screen);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(net, lij_param)
+{
+ IE_START(;);
+
+ if(ielen != 1)
+ goto rej;
+
+ ie->screen = *msg->b_rptr++ & 0xf;
+
+ IE_END(LIJ_PARAM);
+}
+
+/**********************************************************************/
+
+DEF_IE_PRINT(net, lij_seqno)
+{
+ if(uni_print_iehdr("lij_seqno", &ie->h, cx))
+ return;
+ uni_print_entry(cx, "seqno", "0x%x", ie->seqno);
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, lij_seqno)
+{
+ UNUSED(cx); UNUSED(ie);
+
+ return 0;
+}
+
+DEF_IE_ENCODE(net, lij_seqno)
+{
+ START_IE(lij_seqno, UNI_IE_LIJ_SEQNO, 4);
+
+ APP_32BIT(msg, ie->seqno);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(net, lij_seqno)
+{
+ IE_START(;);
+
+ if(ielen != 4)
+ goto rej;
+
+ ie->seqno = *msg->b_rptr++ << 24;
+ ie->seqno |= *msg->b_rptr++ << 16;
+ ie->seqno |= *msg->b_rptr++ << 8;
+ ie->seqno |= *msg->b_rptr++ << 0;
+
+ IE_END(LIJ_SEQNO);
+}
+
+/*********************************************************************
+ *
+ * Connection scope
+ *
+ * References for this IE are:
+ *
+ * UNI4.0 pp. 57...58
+ *
+ * Only NET coding allowed.
+ */
+DEF_IE_PRINT(net, cscope)
+{
+ static const struct uni_print_tbl type_tbl[] = {
+ MKT(UNI_CSCOPE_ORG, org),
+ EOT()
+ };
+ static const struct uni_print_tbl scope_tbl[] = {
+ MKT(UNI_CSCOPE_ORG_LOC, local_network),
+ MKT(UNI_CSCOPE_ORG_LOC_P1, local_network_plus_one),
+ MKT(UNI_CSCOPE_ORG_LOC_P2, local_network_plus_two),
+ MKT(UNI_CSCOPE_ORG_SITE_M1, site_minus_one),
+ MKT(UNI_CSCOPE_ORG_SITE, intra_site),
+ MKT(UNI_CSCOPE_ORG_SITE_P1, site_plus_one),
+ MKT(UNI_CSCOPE_ORG_ORG_M1, organisation_minus_one),
+ MKT(UNI_CSCOPE_ORG_ORG, intra_organisation),
+ MKT(UNI_CSCOPE_ORG_ORG_P1, organisation_plus_one),
+ MKT(UNI_CSCOPE_ORG_COMM_M1, community_minus_one),
+ MKT(UNI_CSCOPE_ORG_COMM, intra_community),
+ MKT(UNI_CSCOPE_ORG_COMM_P1, community_plus_one),
+ MKT(UNI_CSCOPE_ORG_REG, regional),
+ MKT(UNI_CSCOPE_ORG_INTER, inter_regional),
+ MKT(UNI_CSCOPE_ORG_GLOBAL, global),
+ EOT()
+ };
+
+ if(uni_print_iehdr("cscope", &ie->h, cx))
+ return;
+
+ uni_print_tbl("type", ie->type, type_tbl, cx);
+ if(ie->type == UNI_CSCOPE_ORG)
+ uni_print_tbl("scope", (u_int)ie->scope, scope_tbl, cx);
+ else
+ uni_print_entry(cx, "scope", "0x%02x", ie->scope);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, cscope)
+{
+ UNUSED(cx);
+
+ switch(ie->type) {
+
+ default:
+ return -1;
+
+ case UNI_CSCOPE_ORG:
+ switch(ie->scope) {
+
+ default:
+ return -1;
+
+ case UNI_CSCOPE_ORG_LOC:
+ case UNI_CSCOPE_ORG_LOC_P1:
+ case UNI_CSCOPE_ORG_LOC_P2:
+ case UNI_CSCOPE_ORG_SITE_M1:
+ case UNI_CSCOPE_ORG_SITE:
+ case UNI_CSCOPE_ORG_SITE_P1:
+ case UNI_CSCOPE_ORG_ORG_M1:
+ case UNI_CSCOPE_ORG_ORG:
+ case UNI_CSCOPE_ORG_ORG_P1:
+ case UNI_CSCOPE_ORG_COMM_M1:
+ case UNI_CSCOPE_ORG_COMM:
+ case UNI_CSCOPE_ORG_COMM_P1:
+ case UNI_CSCOPE_ORG_REG:
+ case UNI_CSCOPE_ORG_INTER:
+ case UNI_CSCOPE_ORG_GLOBAL:
+ break;
+ }
+ break;
+ }
+ return 0;
+}
+
+DEF_IE_ENCODE(net, cscope)
+{
+ START_IE(cscope, UNI_IE_CSCOPE, 2);
+
+ APP_BYTE(msg, ie->type | 0x80);
+ APP_BYTE(msg, ie->scope);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(net, cscope)
+{
+ IE_START(;);
+ if(ielen != 2)
+ goto rej;
+
+ if((*msg->b_rptr & 0xf0) != 0x80)
+ goto rej;
+
+ ie->type = *msg->b_rptr++ & 0xf;
+ ie->scope = *msg->b_rptr++;
+
+ IE_END(CSCOPE);
+}
+
+/*********************************************************************
+ *
+ * Extended Quality of Service
+ *
+ * References for this IE are:
+ *
+ * UNI4.0 pp. 70...72
+ *
+ * Notes:
+ * Only NET coding.
+ */
+DEF_IE_PRINT(net, exqos)
+{
+ static const struct uni_print_tbl tab[] = {
+ MKT(UNI_EXQOS_USER, user),
+ MKT(UNI_EXQOS_NET, net),
+ EOT()
+ };
+
+ if(uni_print_iehdr("exqos", &ie->h, cx))
+ return;
+
+ uni_print_tbl("origin", ie->origin, tab, cx);
+
+ uni_print_entry(cx, "acceptable", "(");
+ if(ie->h.present & UNI_EXQOS_FACC_P) {
+ if(ie->facc == UNI_EXQOS_ANY_CDV)
+ uni_printf(cx, "ANY");
+ else
+ uni_printf(cx, "%d", ie->facc);
+ }
+ uni_putc(',', cx);
+ if(ie->h.present & UNI_EXQOS_BACC_P) {
+ if(ie->bacc == UNI_EXQOS_ANY_CDV)
+ uni_printf(cx, "ANY");
+ else
+ uni_printf(cx, "%d", ie->bacc);
+ }
+ uni_putc(')', cx);
+
+ uni_print_entry(cx, "cumulative", "(");
+ if(ie->h.present & UNI_EXQOS_FCUM_P)
+ uni_printf(cx, "%d", ie->fcum);
+ uni_putc(',', cx);
+ if(ie->h.present & UNI_EXQOS_BCUM_P)
+ uni_printf(cx, "%d", ie->bcum);
+ uni_putc(')', cx);
+
+ uni_print_entry(cx, "clrid", "(");
+ if(ie->h.present & UNI_EXQOS_FCLR_P) {
+ if(ie->fclr == UNI_EXQOS_ANY_CLR)
+ uni_printf(cx, "ANY");
+ else
+ uni_printf(cx, "%d", ie->fclr);
+ }
+ uni_putc(',', cx);
+ if(ie->h.present & UNI_EXQOS_BCLR_P) {
+ if(ie->bclr == UNI_EXQOS_ANY_CLR)
+ uni_printf(cx, "ANY");
+ else
+ uni_printf(cx, "%d", ie->bclr);
+ }
+ uni_putc(')', cx);
+
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(net, exqos)
+{
+ UNUSED(cx);
+
+ switch(ie->origin) {
+ case UNI_EXQOS_USER:
+ case UNI_EXQOS_NET:
+ break;
+
+ default:
+ return -1;
+ }
+ if(ie->h.present & UNI_EXQOS_FACC_P)
+ if(!(ie->h.present & UNI_EXQOS_FCUM_P))
+ return -1;
+ if(ie->h.present & UNI_EXQOS_BACC_P)
+ if(!(ie->h.present & UNI_EXQOS_BCUM_P))
+ return -1;
+
+ if(ie->h.present & UNI_EXQOS_FACC_P)
+ if(ie->facc >= 1 << 24)
+ return -1;
+ if(ie->h.present & UNI_EXQOS_BACC_P)
+ if(ie->bacc >= 1 << 24)
+ return -1;
+ if(ie->h.present & UNI_EXQOS_FCUM_P)
+ if(ie->fcum >= 1 << 24)
+ return -1;
+ if(ie->h.present & UNI_EXQOS_BCUM_P)
+ if(ie->bcum >= 1 << 24)
+ return -1;
+
+ if(ie->h.present & UNI_EXQOS_FCLR_P)
+ if(ie->fclr==0 || (ie->fclr>15 && ie->fclr!=UNI_EXQOS_ANY_CLR))
+ return -1;
+ if(ie->h.present & UNI_EXQOS_BCLR_P)
+ if(ie->bclr==0 || (ie->bclr>15 && ie->bclr!=UNI_EXQOS_ANY_CLR))
+ return -1;
+ return 0;
+}
+
+DEF_IE_ENCODE(net, exqos)
+{
+ START_IE(exqos, UNI_IE_EXQOS, 21);
+
+ APP_BYTE(msg, ie->origin);
+
+ APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_FACC_P,
+ UNI_EXQOS_FACC_ID, ie->facc);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_BACC_P,
+ UNI_EXQOS_BACC_ID, ie->bacc);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_FCUM_P,
+ UNI_EXQOS_FCUM_ID, ie->fcum);
+ APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_BCUM_P,
+ UNI_EXQOS_BCUM_ID, ie->bcum);
+
+ APP_OPT_BYTE(msg, ie->h.present, UNI_EXQOS_FCLR_P,
+ UNI_EXQOS_FCLR_ID, ie->fclr);
+ APP_OPT_BYTE(msg, ie->h.present, UNI_EXQOS_BCLR_P,
+ UNI_EXQOS_BCLR_ID, ie->bclr);
+
+ SET_IE_LEN(msg);
+ return 0;
+}
+
+DEF_IE_DECODE(net, exqos)
+{
+ IE_START(;);
+
+ if(ielen < 1 || ielen > 21)
+ goto rej;
+
+ ie->origin = *msg->b_rptr++;
+ ielen--;
+
+ while(ielen--) {
+ switch(*msg->b_rptr++) {
+
+ default:
+ goto rej;
+
+ DEC_GETF3(EXQOS_FACC, facc, ie->h.present);
+ DEC_GETF3(EXQOS_BACC, bacc, ie->h.present);
+ DEC_GETF3(EXQOS_FCUM, fcum, ie->h.present);
+ DEC_GETF3(EXQOS_BCUM, bcum, ie->h.present);
+
+ DEC_GETF1(EXQOS_FCLR, fclr, ie->h.present);
+ DEC_GETF1(EXQOS_BCLR, bclr, ie->h.present);
+
+ }
+ }
+ IE_END(EXQOS);
+}
+
+/**************************************************************
+ *
+ * Free form IE (for testing mainly)
+ */
+DEF_IE_PRINT(itu, unrec)
+{
+ u_int i;
+
+ if (uni_print_iehdr("unrec", &ie->h, cx))
+ return;
+ uni_print_entry(cx, "len", "%u", ie->len);
+ uni_print_entry(cx, "data", "(");
+ for (i = 0; i < ie->len; i++)
+ uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->data[i]);
+ uni_printf(cx, ")");
+ uni_print_ieend(cx);
+}
+
+DEF_IE_CHECK(itu, unrec)
+{
+ UNUSED(cx);
+
+ if (ie->len > sizeof(ie->data))
+ return (-1);
+
+ return (0);
+}
+
+DEF_IE_ENCODE(itu, unrec)
+{
+ START_IE2(unrec, UNI_IE_UNREC, ie->len, ie->id);
+
+ APP_BUF(msg, ie->data, ie->len);
+
+ SET_IE_LEN(msg);
+ return (0);
+}
+
+DEF_IE_DECODE(itu, unrec)
+{
+ IE_START(;);
+
+ if (ielen > sizeof(ie->data) / sizeof(ie->data[0]) || ielen < 1)
+ goto rej;
+
+ ie->len = ielen;
+ ielen = 0;
+ (void)memcpy(ie->data, msg->b_rptr, ie->len);
+ msg->b_rptr += ie->len;
+
+ IE_END(UNREC);
+}
diff --git a/sys/contrib/ngatm/netnatm/msg/uni_ie.h b/sys/contrib/ngatm/netnatm/msg/uni_ie.h
new file mode 100644
index 000000000000..f24c560fb8de
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uni_ie.h
@@ -0,0 +1,57 @@
+/* This file was created automatically
+ * Source file: $Begemot: libunimsg/atm/msg/ie.def,v 1.3 2003/09/19 11:58:15 hbb Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _NETNATM_MSG_UNI_IE_H_
+#define _NETNATM_MSG_UNI_IE_H_
+
+union uni_ieall {
+ struct uni_iehdr h;
+ struct uni_ie_cause cause;
+ struct uni_ie_callstate callstate;
+ struct uni_ie_facility facility;
+ struct uni_ie_notify notify;
+ struct uni_ie_eetd eetd;
+ struct uni_ie_conned conned;
+ struct uni_ie_connedsub connedsub;
+ struct uni_ie_epref epref;
+ struct uni_ie_epstate epstate;
+ struct uni_ie_aal aal;
+ struct uni_ie_traffic traffic;
+ struct uni_ie_connid connid;
+ struct uni_ie_qos qos;
+ struct uni_ie_bhli bhli;
+ struct uni_ie_bearer bearer;
+ struct uni_ie_blli blli;
+ struct uni_ie_lshift lshift;
+ struct uni_ie_nlshift nlshift;
+ struct uni_ie_scompl scompl;
+ struct uni_ie_repeat repeat;
+ struct uni_ie_calling calling;
+ struct uni_ie_callingsub callingsub;
+ struct uni_ie_called called;
+ struct uni_ie_calledsub calledsub;
+ struct uni_ie_tns tns;
+ struct uni_ie_restart restart;
+ struct uni_ie_uu uu;
+ struct uni_ie_git git;
+ struct uni_ie_mintraffic mintraffic;
+ struct uni_ie_atraffic atraffic;
+ struct uni_ie_abrsetup abrsetup;
+ struct uni_ie_report report;
+ struct uni_ie_called_soft called_soft;
+ struct uni_ie_crankback crankback;
+ struct uni_ie_dtl dtl;
+ struct uni_ie_calling_soft calling_soft;
+ struct uni_ie_abradd abradd;
+ struct uni_ie_lij_callid lij_callid;
+ struct uni_ie_lij_param lij_param;
+ struct uni_ie_lij_seqno lij_seqno;
+ struct uni_ie_cscope cscope;
+ struct uni_ie_exqos exqos;
+ struct uni_ie_mdcr mdcr;
+ struct uni_ie_unrec unrec;
+};
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/msg/uni_ietab.h b/sys/contrib/ngatm/netnatm/msg/uni_ietab.h
new file mode 100644
index 000000000000..62cba33cd91d
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uni_ietab.h
@@ -0,0 +1,958 @@
+/* This file was created automatically
+ * Source file: $Begemot: libunimsg/atm/msg/ie.def,v 1.3 2003/09/19 11:58:15 hbb Exp $
+ * $FreeBSD$
+ */
+
+
+static void uni_ie_print_itu_cause(struct uni_ie_cause *, struct unicx *);
+static int uni_ie_check_itu_cause(struct uni_ie_cause *, struct unicx *);
+static int uni_ie_encode_itu_cause(struct uni_msg *, struct uni_ie_cause *, struct unicx *);
+static int uni_ie_decode_itu_cause(struct uni_ie_cause *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_cause = {
+ 0,
+ 34,
+ (uni_print_f)uni_ie_print_itu_cause,
+ (uni_check_f)uni_ie_check_itu_cause,
+ (uni_encode_f)uni_ie_encode_itu_cause,
+ (uni_decode_f)uni_ie_decode_itu_cause
+};
+
+static void uni_ie_print_net_cause(struct uni_ie_cause *, struct unicx *);
+static int uni_ie_check_net_cause(struct uni_ie_cause *, struct unicx *);
+static int uni_ie_encode_net_cause(struct uni_msg *, struct uni_ie_cause *, struct unicx *);
+static int uni_ie_decode_net_cause(struct uni_ie_cause *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_cause = {
+ 0,
+ 34,
+ (uni_print_f)uni_ie_print_net_cause,
+ (uni_check_f)uni_ie_check_net_cause,
+ (uni_encode_f)uni_ie_encode_net_cause,
+ (uni_decode_f)uni_ie_decode_net_cause
+};
+
+static void uni_ie_print_itu_callstate(struct uni_ie_callstate *, struct unicx *);
+static int uni_ie_check_itu_callstate(struct uni_ie_callstate *, struct unicx *);
+static int uni_ie_encode_itu_callstate(struct uni_msg *, struct uni_ie_callstate *, struct unicx *);
+static int uni_ie_decode_itu_callstate(struct uni_ie_callstate *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_callstate = {
+ 0,
+ 5,
+ (uni_print_f)uni_ie_print_itu_callstate,
+ (uni_check_f)uni_ie_check_itu_callstate,
+ (uni_encode_f)uni_ie_encode_itu_callstate,
+ (uni_decode_f)uni_ie_decode_itu_callstate
+};
+
+static void uni_ie_print_itu_facility(struct uni_ie_facility *, struct unicx *);
+static int uni_ie_check_itu_facility(struct uni_ie_facility *, struct unicx *);
+static int uni_ie_encode_itu_facility(struct uni_msg *, struct uni_ie_facility *, struct unicx *);
+static int uni_ie_decode_itu_facility(struct uni_ie_facility *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_facility = {
+ 0,
+ UNI_FACILITY_MAXAPDU+1+4,
+ (uni_print_f)uni_ie_print_itu_facility,
+ (uni_check_f)uni_ie_check_itu_facility,
+ (uni_encode_f)uni_ie_encode_itu_facility,
+ (uni_decode_f)uni_ie_decode_itu_facility
+};
+
+static void uni_ie_print_itu_notify(struct uni_ie_notify *, struct unicx *);
+static int uni_ie_check_itu_notify(struct uni_ie_notify *, struct unicx *);
+static int uni_ie_encode_itu_notify(struct uni_msg *, struct uni_ie_notify *, struct unicx *);
+static int uni_ie_decode_itu_notify(struct uni_ie_notify *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_notify = {
+ 0,
+ UNI_NOTIFY_MAXLEN+4,
+ (uni_print_f)uni_ie_print_itu_notify,
+ (uni_check_f)uni_ie_check_itu_notify,
+ (uni_encode_f)uni_ie_encode_itu_notify,
+ (uni_decode_f)uni_ie_decode_itu_notify
+};
+
+static void uni_ie_print_itu_eetd(struct uni_ie_eetd *, struct unicx *);
+static int uni_ie_check_itu_eetd(struct uni_ie_eetd *, struct unicx *);
+static int uni_ie_encode_itu_eetd(struct uni_msg *, struct uni_ie_eetd *, struct unicx *);
+static int uni_ie_decode_itu_eetd(struct uni_ie_eetd *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_eetd = {
+ 0,
+ 11,
+ (uni_print_f)uni_ie_print_itu_eetd,
+ (uni_check_f)uni_ie_check_itu_eetd,
+ (uni_encode_f)uni_ie_encode_itu_eetd,
+ (uni_decode_f)uni_ie_decode_itu_eetd
+};
+
+static void uni_ie_print_net_eetd(struct uni_ie_eetd *, struct unicx *);
+static int uni_ie_check_net_eetd(struct uni_ie_eetd *, struct unicx *);
+static int uni_ie_encode_net_eetd(struct uni_msg *, struct uni_ie_eetd *, struct unicx *);
+static int uni_ie_decode_net_eetd(struct uni_ie_eetd *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_eetd = {
+ 0,
+ 13,
+ (uni_print_f)uni_ie_print_net_eetd,
+ (uni_check_f)uni_ie_check_net_eetd,
+ (uni_encode_f)uni_ie_encode_net_eetd,
+ (uni_decode_f)uni_ie_decode_net_eetd
+};
+
+static void uni_ie_print_itu_conned(struct uni_ie_conned *, struct unicx *);
+static int uni_ie_check_itu_conned(struct uni_ie_conned *, struct unicx *);
+static int uni_ie_encode_itu_conned(struct uni_msg *, struct uni_ie_conned *, struct unicx *);
+static int uni_ie_decode_itu_conned(struct uni_ie_conned *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_conned = {
+ 0,
+ 25,
+ (uni_print_f)uni_ie_print_itu_conned,
+ (uni_check_f)uni_ie_check_itu_conned,
+ (uni_encode_f)uni_ie_encode_itu_conned,
+ (uni_decode_f)uni_ie_decode_itu_conned
+};
+
+static void uni_ie_print_itu_connedsub(struct uni_ie_connedsub *, struct unicx *);
+static int uni_ie_check_itu_connedsub(struct uni_ie_connedsub *, struct unicx *);
+static int uni_ie_encode_itu_connedsub(struct uni_msg *, struct uni_ie_connedsub *, struct unicx *);
+static int uni_ie_decode_itu_connedsub(struct uni_ie_connedsub *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_connedsub = {
+ UNIFL_ACCESS,
+ 25,
+ (uni_print_f)uni_ie_print_itu_connedsub,
+ (uni_check_f)uni_ie_check_itu_connedsub,
+ (uni_encode_f)uni_ie_encode_itu_connedsub,
+ (uni_decode_f)uni_ie_decode_itu_connedsub
+};
+
+static void uni_ie_print_itu_epref(struct uni_ie_epref *, struct unicx *);
+static int uni_ie_check_itu_epref(struct uni_ie_epref *, struct unicx *);
+static int uni_ie_encode_itu_epref(struct uni_msg *, struct uni_ie_epref *, struct unicx *);
+static int uni_ie_decode_itu_epref(struct uni_ie_epref *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_epref = {
+ 0,
+ 7,
+ (uni_print_f)uni_ie_print_itu_epref,
+ (uni_check_f)uni_ie_check_itu_epref,
+ (uni_encode_f)uni_ie_encode_itu_epref,
+ (uni_decode_f)uni_ie_decode_itu_epref
+};
+
+static void uni_ie_print_itu_epstate(struct uni_ie_epstate *, struct unicx *);
+static int uni_ie_check_itu_epstate(struct uni_ie_epstate *, struct unicx *);
+static int uni_ie_encode_itu_epstate(struct uni_msg *, struct uni_ie_epstate *, struct unicx *);
+static int uni_ie_decode_itu_epstate(struct uni_ie_epstate *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_epstate = {
+ 0,
+ 5,
+ (uni_print_f)uni_ie_print_itu_epstate,
+ (uni_check_f)uni_ie_check_itu_epstate,
+ (uni_encode_f)uni_ie_encode_itu_epstate,
+ (uni_decode_f)uni_ie_decode_itu_epstate
+};
+
+static void uni_ie_print_itu_aal(struct uni_ie_aal *, struct unicx *);
+static int uni_ie_check_itu_aal(struct uni_ie_aal *, struct unicx *);
+static int uni_ie_encode_itu_aal(struct uni_msg *, struct uni_ie_aal *, struct unicx *);
+static int uni_ie_decode_itu_aal(struct uni_ie_aal *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_aal = {
+ UNIFL_ACCESS,
+ 21,
+ (uni_print_f)uni_ie_print_itu_aal,
+ (uni_check_f)uni_ie_check_itu_aal,
+ (uni_encode_f)uni_ie_encode_itu_aal,
+ (uni_decode_f)uni_ie_decode_itu_aal
+};
+
+static void uni_ie_print_itu_traffic(struct uni_ie_traffic *, struct unicx *);
+static int uni_ie_check_itu_traffic(struct uni_ie_traffic *, struct unicx *);
+static int uni_ie_encode_itu_traffic(struct uni_msg *, struct uni_ie_traffic *, struct unicx *);
+static int uni_ie_decode_itu_traffic(struct uni_ie_traffic *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_traffic = {
+ 0,
+ 30,
+ (uni_print_f)uni_ie_print_itu_traffic,
+ (uni_check_f)uni_ie_check_itu_traffic,
+ (uni_encode_f)uni_ie_encode_itu_traffic,
+ (uni_decode_f)uni_ie_decode_itu_traffic
+};
+
+static const struct iedecl decl_net_traffic = {
+ UNIFL_DEFAULT,
+ 0,
+ (uni_print_f)NULL,
+ (uni_check_f)NULL,
+ (uni_encode_f)NULL,
+ (uni_decode_f)NULL
+};
+
+static void uni_ie_print_itu_connid(struct uni_ie_connid *, struct unicx *);
+static int uni_ie_check_itu_connid(struct uni_ie_connid *, struct unicx *);
+static int uni_ie_encode_itu_connid(struct uni_msg *, struct uni_ie_connid *, struct unicx *);
+static int uni_ie_decode_itu_connid(struct uni_ie_connid *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_connid = {
+ 0,
+ 9,
+ (uni_print_f)uni_ie_print_itu_connid,
+ (uni_check_f)uni_ie_check_itu_connid,
+ (uni_encode_f)uni_ie_encode_itu_connid,
+ (uni_decode_f)uni_ie_decode_itu_connid
+};
+
+static void uni_ie_print_itu_qos(struct uni_ie_qos *, struct unicx *);
+static int uni_ie_check_itu_qos(struct uni_ie_qos *, struct unicx *);
+static int uni_ie_encode_itu_qos(struct uni_msg *, struct uni_ie_qos *, struct unicx *);
+static int uni_ie_decode_itu_qos(struct uni_ie_qos *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_qos = {
+ 0,
+ 6,
+ (uni_print_f)uni_ie_print_itu_qos,
+ (uni_check_f)uni_ie_check_itu_qos,
+ (uni_encode_f)uni_ie_encode_itu_qos,
+ (uni_decode_f)uni_ie_decode_itu_qos
+};
+
+static void uni_ie_print_net_qos(struct uni_ie_qos *, struct unicx *);
+static int uni_ie_check_net_qos(struct uni_ie_qos *, struct unicx *);
+static int uni_ie_encode_net_qos(struct uni_msg *, struct uni_ie_qos *, struct unicx *);
+static int uni_ie_decode_net_qos(struct uni_ie_qos *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_qos = {
+ 0,
+ 6,
+ (uni_print_f)uni_ie_print_net_qos,
+ (uni_check_f)uni_ie_check_net_qos,
+ (uni_encode_f)uni_ie_encode_net_qos,
+ (uni_decode_f)uni_ie_decode_net_qos
+};
+
+static void uni_ie_print_itu_bhli(struct uni_ie_bhli *, struct unicx *);
+static int uni_ie_check_itu_bhli(struct uni_ie_bhli *, struct unicx *);
+static int uni_ie_encode_itu_bhli(struct uni_msg *, struct uni_ie_bhli *, struct unicx *);
+static int uni_ie_decode_itu_bhli(struct uni_ie_bhli *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_bhli = {
+ UNIFL_ACCESS,
+ 13,
+ (uni_print_f)uni_ie_print_itu_bhli,
+ (uni_check_f)uni_ie_check_itu_bhli,
+ (uni_encode_f)uni_ie_encode_itu_bhli,
+ (uni_decode_f)uni_ie_decode_itu_bhli
+};
+
+static void uni_ie_print_itu_bearer(struct uni_ie_bearer *, struct unicx *);
+static int uni_ie_check_itu_bearer(struct uni_ie_bearer *, struct unicx *);
+static int uni_ie_encode_itu_bearer(struct uni_msg *, struct uni_ie_bearer *, struct unicx *);
+static int uni_ie_decode_itu_bearer(struct uni_ie_bearer *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_bearer = {
+ 0,
+ 7,
+ (uni_print_f)uni_ie_print_itu_bearer,
+ (uni_check_f)uni_ie_check_itu_bearer,
+ (uni_encode_f)uni_ie_encode_itu_bearer,
+ (uni_decode_f)uni_ie_decode_itu_bearer
+};
+
+static void uni_ie_print_itu_blli(struct uni_ie_blli *, struct unicx *);
+static int uni_ie_check_itu_blli(struct uni_ie_blli *, struct unicx *);
+static int uni_ie_encode_itu_blli(struct uni_msg *, struct uni_ie_blli *, struct unicx *);
+static int uni_ie_decode_itu_blli(struct uni_ie_blli *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_blli = {
+ UNIFL_ACCESS,
+ 17,
+ (uni_print_f)uni_ie_print_itu_blli,
+ (uni_check_f)uni_ie_check_itu_blli,
+ (uni_encode_f)uni_ie_encode_itu_blli,
+ (uni_decode_f)uni_ie_decode_itu_blli
+};
+
+static void uni_ie_print_itu_lshift(struct uni_ie_lshift *, struct unicx *);
+static int uni_ie_check_itu_lshift(struct uni_ie_lshift *, struct unicx *);
+static int uni_ie_encode_itu_lshift(struct uni_msg *, struct uni_ie_lshift *, struct unicx *);
+static int uni_ie_decode_itu_lshift(struct uni_ie_lshift *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_lshift = {
+ 0,
+ 5,
+ (uni_print_f)uni_ie_print_itu_lshift,
+ (uni_check_f)uni_ie_check_itu_lshift,
+ (uni_encode_f)uni_ie_encode_itu_lshift,
+ (uni_decode_f)uni_ie_decode_itu_lshift
+};
+
+static void uni_ie_print_itu_nlshift(struct uni_ie_nlshift *, struct unicx *);
+static int uni_ie_check_itu_nlshift(struct uni_ie_nlshift *, struct unicx *);
+static int uni_ie_encode_itu_nlshift(struct uni_msg *, struct uni_ie_nlshift *, struct unicx *);
+static int uni_ie_decode_itu_nlshift(struct uni_ie_nlshift *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_nlshift = {
+ 0,
+ 5,
+ (uni_print_f)uni_ie_print_itu_nlshift,
+ (uni_check_f)uni_ie_check_itu_nlshift,
+ (uni_encode_f)uni_ie_encode_itu_nlshift,
+ (uni_decode_f)uni_ie_decode_itu_nlshift
+};
+
+static void uni_ie_print_itu_scompl(struct uni_ie_scompl *, struct unicx *);
+static int uni_ie_check_itu_scompl(struct uni_ie_scompl *, struct unicx *);
+static int uni_ie_encode_itu_scompl(struct uni_msg *, struct uni_ie_scompl *, struct unicx *);
+static int uni_ie_decode_itu_scompl(struct uni_ie_scompl *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_scompl = {
+ 0,
+ 5,
+ (uni_print_f)uni_ie_print_itu_scompl,
+ (uni_check_f)uni_ie_check_itu_scompl,
+ (uni_encode_f)uni_ie_encode_itu_scompl,
+ (uni_decode_f)uni_ie_decode_itu_scompl
+};
+
+static void uni_ie_print_itu_repeat(struct uni_ie_repeat *, struct unicx *);
+static int uni_ie_check_itu_repeat(struct uni_ie_repeat *, struct unicx *);
+static int uni_ie_encode_itu_repeat(struct uni_msg *, struct uni_ie_repeat *, struct unicx *);
+static int uni_ie_decode_itu_repeat(struct uni_ie_repeat *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_repeat = {
+ 0,
+ 5,
+ (uni_print_f)uni_ie_print_itu_repeat,
+ (uni_check_f)uni_ie_check_itu_repeat,
+ (uni_encode_f)uni_ie_encode_itu_repeat,
+ (uni_decode_f)uni_ie_decode_itu_repeat
+};
+
+static void uni_ie_print_itu_calling(struct uni_ie_calling *, struct unicx *);
+static int uni_ie_check_itu_calling(struct uni_ie_calling *, struct unicx *);
+static int uni_ie_encode_itu_calling(struct uni_msg *, struct uni_ie_calling *, struct unicx *);
+static int uni_ie_decode_itu_calling(struct uni_ie_calling *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_calling = {
+ 0,
+ 26,
+ (uni_print_f)uni_ie_print_itu_calling,
+ (uni_check_f)uni_ie_check_itu_calling,
+ (uni_encode_f)uni_ie_encode_itu_calling,
+ (uni_decode_f)uni_ie_decode_itu_calling
+};
+
+static void uni_ie_print_itu_callingsub(struct uni_ie_callingsub *, struct unicx *);
+static int uni_ie_check_itu_callingsub(struct uni_ie_callingsub *, struct unicx *);
+static int uni_ie_encode_itu_callingsub(struct uni_msg *, struct uni_ie_callingsub *, struct unicx *);
+static int uni_ie_decode_itu_callingsub(struct uni_ie_callingsub *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_callingsub = {
+ UNIFL_ACCESS,
+ 25,
+ (uni_print_f)uni_ie_print_itu_callingsub,
+ (uni_check_f)uni_ie_check_itu_callingsub,
+ (uni_encode_f)uni_ie_encode_itu_callingsub,
+ (uni_decode_f)uni_ie_decode_itu_callingsub
+};
+
+static void uni_ie_print_itu_called(struct uni_ie_called *, struct unicx *);
+static int uni_ie_check_itu_called(struct uni_ie_called *, struct unicx *);
+static int uni_ie_encode_itu_called(struct uni_msg *, struct uni_ie_called *, struct unicx *);
+static int uni_ie_decode_itu_called(struct uni_ie_called *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_called = {
+ 0,
+ 25,
+ (uni_print_f)uni_ie_print_itu_called,
+ (uni_check_f)uni_ie_check_itu_called,
+ (uni_encode_f)uni_ie_encode_itu_called,
+ (uni_decode_f)uni_ie_decode_itu_called
+};
+
+static void uni_ie_print_itu_calledsub(struct uni_ie_calledsub *, struct unicx *);
+static int uni_ie_check_itu_calledsub(struct uni_ie_calledsub *, struct unicx *);
+static int uni_ie_encode_itu_calledsub(struct uni_msg *, struct uni_ie_calledsub *, struct unicx *);
+static int uni_ie_decode_itu_calledsub(struct uni_ie_calledsub *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_calledsub = {
+ UNIFL_ACCESS,
+ 25,
+ (uni_print_f)uni_ie_print_itu_calledsub,
+ (uni_check_f)uni_ie_check_itu_calledsub,
+ (uni_encode_f)uni_ie_encode_itu_calledsub,
+ (uni_decode_f)uni_ie_decode_itu_calledsub
+};
+
+static void uni_ie_print_itu_tns(struct uni_ie_tns *, struct unicx *);
+static int uni_ie_check_itu_tns(struct uni_ie_tns *, struct unicx *);
+static int uni_ie_encode_itu_tns(struct uni_msg *, struct uni_ie_tns *, struct unicx *);
+static int uni_ie_decode_itu_tns(struct uni_ie_tns *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_tns = {
+ 0,
+ 9,
+ (uni_print_f)uni_ie_print_itu_tns,
+ (uni_check_f)uni_ie_check_itu_tns,
+ (uni_encode_f)uni_ie_encode_itu_tns,
+ (uni_decode_f)uni_ie_decode_itu_tns
+};
+
+static const struct iedecl decl_net_tns = {
+ UNIFL_DEFAULT,
+ 0,
+ (uni_print_f)NULL,
+ (uni_check_f)NULL,
+ (uni_encode_f)NULL,
+ (uni_decode_f)NULL
+};
+
+static void uni_ie_print_itu_restart(struct uni_ie_restart *, struct unicx *);
+static int uni_ie_check_itu_restart(struct uni_ie_restart *, struct unicx *);
+static int uni_ie_encode_itu_restart(struct uni_msg *, struct uni_ie_restart *, struct unicx *);
+static int uni_ie_decode_itu_restart(struct uni_ie_restart *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_restart = {
+ 0,
+ 5,
+ (uni_print_f)uni_ie_print_itu_restart,
+ (uni_check_f)uni_ie_check_itu_restart,
+ (uni_encode_f)uni_ie_encode_itu_restart,
+ (uni_decode_f)uni_ie_decode_itu_restart
+};
+
+static void uni_ie_print_itu_uu(struct uni_ie_uu *, struct unicx *);
+static int uni_ie_check_itu_uu(struct uni_ie_uu *, struct unicx *);
+static int uni_ie_encode_itu_uu(struct uni_msg *, struct uni_ie_uu *, struct unicx *);
+static int uni_ie_decode_itu_uu(struct uni_ie_uu *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_uu = {
+ UNIFL_ACCESS,
+ UNI_UU_MAXLEN+4,
+ (uni_print_f)uni_ie_print_itu_uu,
+ (uni_check_f)uni_ie_check_itu_uu,
+ (uni_encode_f)uni_ie_encode_itu_uu,
+ (uni_decode_f)uni_ie_decode_itu_uu
+};
+
+static void uni_ie_print_net_git(struct uni_ie_git *, struct unicx *);
+static int uni_ie_check_net_git(struct uni_ie_git *, struct unicx *);
+static int uni_ie_encode_net_git(struct uni_msg *, struct uni_ie_git *, struct unicx *);
+static int uni_ie_decode_net_git(struct uni_ie_git *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_git = {
+ 0,
+ 33,
+ (uni_print_f)uni_ie_print_net_git,
+ (uni_check_f)uni_ie_check_net_git,
+ (uni_encode_f)uni_ie_encode_net_git,
+ (uni_decode_f)uni_ie_decode_net_git
+};
+
+static void uni_ie_print_itu_mintraffic(struct uni_ie_mintraffic *, struct unicx *);
+static int uni_ie_check_itu_mintraffic(struct uni_ie_mintraffic *, struct unicx *);
+static int uni_ie_encode_itu_mintraffic(struct uni_msg *, struct uni_ie_mintraffic *, struct unicx *);
+static int uni_ie_decode_itu_mintraffic(struct uni_ie_mintraffic *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_mintraffic = {
+ 0,
+ 20,
+ (uni_print_f)uni_ie_print_itu_mintraffic,
+ (uni_check_f)uni_ie_check_itu_mintraffic,
+ (uni_encode_f)uni_ie_encode_itu_mintraffic,
+ (uni_decode_f)uni_ie_decode_itu_mintraffic
+};
+
+static const struct iedecl decl_net_mintraffic = {
+ UNIFL_DEFAULT,
+ 0,
+ (uni_print_f)NULL,
+ (uni_check_f)NULL,
+ (uni_encode_f)NULL,
+ (uni_decode_f)NULL
+};
+
+static void uni_ie_print_itu_atraffic(struct uni_ie_atraffic *, struct unicx *);
+static int uni_ie_check_itu_atraffic(struct uni_ie_atraffic *, struct unicx *);
+static int uni_ie_encode_itu_atraffic(struct uni_msg *, struct uni_ie_atraffic *, struct unicx *);
+static int uni_ie_decode_itu_atraffic(struct uni_ie_atraffic *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_atraffic = {
+ 0,
+ 30,
+ (uni_print_f)uni_ie_print_itu_atraffic,
+ (uni_check_f)uni_ie_check_itu_atraffic,
+ (uni_encode_f)uni_ie_encode_itu_atraffic,
+ (uni_decode_f)uni_ie_decode_itu_atraffic
+};
+
+static const struct iedecl decl_net_atraffic = {
+ UNIFL_DEFAULT,
+ 0,
+ (uni_print_f)NULL,
+ (uni_check_f)NULL,
+ (uni_encode_f)NULL,
+ (uni_decode_f)NULL
+};
+
+static void uni_ie_print_net_abrsetup(struct uni_ie_abrsetup *, struct unicx *);
+static int uni_ie_check_net_abrsetup(struct uni_ie_abrsetup *, struct unicx *);
+static int uni_ie_encode_net_abrsetup(struct uni_msg *, struct uni_ie_abrsetup *, struct unicx *);
+static int uni_ie_decode_net_abrsetup(struct uni_ie_abrsetup *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_abrsetup = {
+ 0,
+ 36,
+ (uni_print_f)uni_ie_print_net_abrsetup,
+ (uni_check_f)uni_ie_check_net_abrsetup,
+ (uni_encode_f)uni_ie_encode_net_abrsetup,
+ (uni_decode_f)uni_ie_decode_net_abrsetup
+};
+
+static void uni_ie_print_itu_report(struct uni_ie_report *, struct unicx *);
+static int uni_ie_check_itu_report(struct uni_ie_report *, struct unicx *);
+static int uni_ie_encode_itu_report(struct uni_msg *, struct uni_ie_report *, struct unicx *);
+static int uni_ie_decode_itu_report(struct uni_ie_report *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_report = {
+ 0,
+ 5,
+ (uni_print_f)uni_ie_print_itu_report,
+ (uni_check_f)uni_ie_check_itu_report,
+ (uni_encode_f)uni_ie_encode_itu_report,
+ (uni_decode_f)uni_ie_decode_itu_report
+};
+
+static void uni_ie_print_net_called_soft(struct uni_ie_called_soft *, struct unicx *);
+static int uni_ie_check_net_called_soft(struct uni_ie_called_soft *, struct unicx *);
+static int uni_ie_encode_net_called_soft(struct uni_msg *, struct uni_ie_called_soft *, struct unicx *);
+static int uni_ie_decode_net_called_soft(struct uni_ie_called_soft *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_called_soft = {
+ 0,
+ 11,
+ (uni_print_f)uni_ie_print_net_called_soft,
+ (uni_check_f)uni_ie_check_net_called_soft,
+ (uni_encode_f)uni_ie_encode_net_called_soft,
+ (uni_decode_f)uni_ie_decode_net_called_soft
+};
+
+static void uni_ie_print_net_crankback(struct uni_ie_crankback *, struct unicx *);
+static int uni_ie_check_net_crankback(struct uni_ie_crankback *, struct unicx *);
+static int uni_ie_encode_net_crankback(struct uni_msg *, struct uni_ie_crankback *, struct unicx *);
+static int uni_ie_decode_net_crankback(struct uni_ie_crankback *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_crankback = {
+ 0,
+ 72,
+ (uni_print_f)uni_ie_print_net_crankback,
+ (uni_check_f)uni_ie_check_net_crankback,
+ (uni_encode_f)uni_ie_encode_net_crankback,
+ (uni_decode_f)uni_ie_decode_net_crankback
+};
+
+static void uni_ie_print_net_dtl(struct uni_ie_dtl *, struct unicx *);
+static int uni_ie_check_net_dtl(struct uni_ie_dtl *, struct unicx *);
+static int uni_ie_encode_net_dtl(struct uni_msg *, struct uni_ie_dtl *, struct unicx *);
+static int uni_ie_decode_net_dtl(struct uni_ie_dtl *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_dtl = {
+ 0,
+ UNI_DTL_LOGNP_SIZE*UNI_DTL_MAXNUM+6,
+ (uni_print_f)uni_ie_print_net_dtl,
+ (uni_check_f)uni_ie_check_net_dtl,
+ (uni_encode_f)uni_ie_encode_net_dtl,
+ (uni_decode_f)uni_ie_decode_net_dtl
+};
+
+static void uni_ie_print_net_calling_soft(struct uni_ie_calling_soft *, struct unicx *);
+static int uni_ie_check_net_calling_soft(struct uni_ie_calling_soft *, struct unicx *);
+static int uni_ie_encode_net_calling_soft(struct uni_msg *, struct uni_ie_calling_soft *, struct unicx *);
+static int uni_ie_decode_net_calling_soft(struct uni_ie_calling_soft *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_calling_soft = {
+ 0,
+ 10,
+ (uni_print_f)uni_ie_print_net_calling_soft,
+ (uni_check_f)uni_ie_check_net_calling_soft,
+ (uni_encode_f)uni_ie_encode_net_calling_soft,
+ (uni_decode_f)uni_ie_decode_net_calling_soft
+};
+
+static void uni_ie_print_net_abradd(struct uni_ie_abradd *, struct unicx *);
+static int uni_ie_check_net_abradd(struct uni_ie_abradd *, struct unicx *);
+static int uni_ie_encode_net_abradd(struct uni_msg *, struct uni_ie_abradd *, struct unicx *);
+static int uni_ie_decode_net_abradd(struct uni_ie_abradd *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_abradd = {
+ 0,
+ 14,
+ (uni_print_f)uni_ie_print_net_abradd,
+ (uni_check_f)uni_ie_check_net_abradd,
+ (uni_encode_f)uni_ie_encode_net_abradd,
+ (uni_decode_f)uni_ie_decode_net_abradd
+};
+
+static void uni_ie_print_net_lij_callid(struct uni_ie_lij_callid *, struct unicx *);
+static int uni_ie_check_net_lij_callid(struct uni_ie_lij_callid *, struct unicx *);
+static int uni_ie_encode_net_lij_callid(struct uni_msg *, struct uni_ie_lij_callid *, struct unicx *);
+static int uni_ie_decode_net_lij_callid(struct uni_ie_lij_callid *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_lij_callid = {
+ 0,
+ 9,
+ (uni_print_f)uni_ie_print_net_lij_callid,
+ (uni_check_f)uni_ie_check_net_lij_callid,
+ (uni_encode_f)uni_ie_encode_net_lij_callid,
+ (uni_decode_f)uni_ie_decode_net_lij_callid
+};
+
+static void uni_ie_print_net_lij_param(struct uni_ie_lij_param *, struct unicx *);
+static int uni_ie_check_net_lij_param(struct uni_ie_lij_param *, struct unicx *);
+static int uni_ie_encode_net_lij_param(struct uni_msg *, struct uni_ie_lij_param *, struct unicx *);
+static int uni_ie_decode_net_lij_param(struct uni_ie_lij_param *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_lij_param = {
+ 0,
+ 5,
+ (uni_print_f)uni_ie_print_net_lij_param,
+ (uni_check_f)uni_ie_check_net_lij_param,
+ (uni_encode_f)uni_ie_encode_net_lij_param,
+ (uni_decode_f)uni_ie_decode_net_lij_param
+};
+
+static void uni_ie_print_net_lij_seqno(struct uni_ie_lij_seqno *, struct unicx *);
+static int uni_ie_check_net_lij_seqno(struct uni_ie_lij_seqno *, struct unicx *);
+static int uni_ie_encode_net_lij_seqno(struct uni_msg *, struct uni_ie_lij_seqno *, struct unicx *);
+static int uni_ie_decode_net_lij_seqno(struct uni_ie_lij_seqno *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_lij_seqno = {
+ 0,
+ 8,
+ (uni_print_f)uni_ie_print_net_lij_seqno,
+ (uni_check_f)uni_ie_check_net_lij_seqno,
+ (uni_encode_f)uni_ie_encode_net_lij_seqno,
+ (uni_decode_f)uni_ie_decode_net_lij_seqno
+};
+
+static void uni_ie_print_net_cscope(struct uni_ie_cscope *, struct unicx *);
+static int uni_ie_check_net_cscope(struct uni_ie_cscope *, struct unicx *);
+static int uni_ie_encode_net_cscope(struct uni_msg *, struct uni_ie_cscope *, struct unicx *);
+static int uni_ie_decode_net_cscope(struct uni_ie_cscope *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_cscope = {
+ 0,
+ 6,
+ (uni_print_f)uni_ie_print_net_cscope,
+ (uni_check_f)uni_ie_check_net_cscope,
+ (uni_encode_f)uni_ie_encode_net_cscope,
+ (uni_decode_f)uni_ie_decode_net_cscope
+};
+
+static void uni_ie_print_net_exqos(struct uni_ie_exqos *, struct unicx *);
+static int uni_ie_check_net_exqos(struct uni_ie_exqos *, struct unicx *);
+static int uni_ie_encode_net_exqos(struct uni_msg *, struct uni_ie_exqos *, struct unicx *);
+static int uni_ie_decode_net_exqos(struct uni_ie_exqos *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_exqos = {
+ 0,
+ 25,
+ (uni_print_f)uni_ie_print_net_exqos,
+ (uni_check_f)uni_ie_check_net_exqos,
+ (uni_encode_f)uni_ie_encode_net_exqos,
+ (uni_decode_f)uni_ie_decode_net_exqos
+};
+
+static void uni_ie_print_net_mdcr(struct uni_ie_mdcr *, struct unicx *);
+static int uni_ie_check_net_mdcr(struct uni_ie_mdcr *, struct unicx *);
+static int uni_ie_encode_net_mdcr(struct uni_msg *, struct uni_ie_mdcr *, struct unicx *);
+static int uni_ie_decode_net_mdcr(struct uni_ie_mdcr *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_net_mdcr = {
+ 0,
+ 13,
+ (uni_print_f)uni_ie_print_net_mdcr,
+ (uni_check_f)uni_ie_check_net_mdcr,
+ (uni_encode_f)uni_ie_encode_net_mdcr,
+ (uni_decode_f)uni_ie_decode_net_mdcr
+};
+
+static void uni_ie_print_itu_unrec(struct uni_ie_unrec *, struct unicx *);
+static int uni_ie_check_itu_unrec(struct uni_ie_unrec *, struct unicx *);
+static int uni_ie_encode_itu_unrec(struct uni_msg *, struct uni_ie_unrec *, struct unicx *);
+static int uni_ie_decode_itu_unrec(struct uni_ie_unrec *, struct uni_msg *, u_int, struct unicx *);
+
+static struct iedecl decl_itu_unrec = {
+ 0,
+ 128,
+ (uni_print_f)uni_ie_print_itu_unrec,
+ (uni_check_f)uni_ie_check_itu_unrec,
+ (uni_encode_f)uni_ie_encode_itu_unrec,
+ (uni_decode_f)uni_ie_decode_itu_unrec
+};
+
+const struct iedecl *uni_ietable[256][4] = {
+ { NULL, NULL, NULL, NULL, }, /* 0x00 */
+ { NULL, NULL, NULL, NULL, }, /* 0x01 */
+ { NULL, NULL, NULL, NULL, }, /* 0x02 */
+ { NULL, NULL, NULL, NULL, }, /* 0x03 */
+ { NULL, NULL, NULL, NULL, }, /* 0x04 */
+ { NULL, NULL, NULL, NULL, }, /* 0x05 */
+ { NULL, NULL, NULL, NULL, }, /* 0x06 */
+ { NULL, NULL, NULL, NULL, }, /* 0x07 */
+ { &decl_itu_cause, NULL, NULL, &decl_net_cause, }, /* 0x08 */
+ { NULL, NULL, NULL, NULL, }, /* 0x09 */
+ { NULL, NULL, NULL, NULL, }, /* 0x0a */
+ { NULL, NULL, NULL, NULL, }, /* 0x0b */
+ { NULL, NULL, NULL, NULL, }, /* 0x0c */
+ { NULL, NULL, NULL, NULL, }, /* 0x0d */
+ { NULL, NULL, NULL, NULL, }, /* 0x0e */
+ { NULL, NULL, NULL, NULL, }, /* 0x0f */
+ { NULL, NULL, NULL, NULL, }, /* 0x10 */
+ { NULL, NULL, NULL, NULL, }, /* 0x11 */
+ { NULL, NULL, NULL, NULL, }, /* 0x12 */
+ { NULL, NULL, NULL, NULL, }, /* 0x13 */
+ { &decl_itu_callstate, NULL, NULL, NULL, }, /* 0x14 */
+ { NULL, NULL, NULL, NULL, }, /* 0x15 */
+ { NULL, NULL, NULL, NULL, }, /* 0x16 */
+ { NULL, NULL, NULL, NULL, }, /* 0x17 */
+ { NULL, NULL, NULL, NULL, }, /* 0x18 */
+ { NULL, NULL, NULL, NULL, }, /* 0x19 */
+ { NULL, NULL, NULL, NULL, }, /* 0x1a */
+ { NULL, NULL, NULL, NULL, }, /* 0x1b */
+ { &decl_itu_facility, NULL, NULL, NULL, }, /* 0x1c */
+ { NULL, NULL, NULL, NULL, }, /* 0x1d */
+ { NULL, NULL, NULL, NULL, }, /* 0x1e */
+ { NULL, NULL, NULL, NULL, }, /* 0x1f */
+ { NULL, NULL, NULL, NULL, }, /* 0x20 */
+ { NULL, NULL, NULL, NULL, }, /* 0x21 */
+ { NULL, NULL, NULL, NULL, }, /* 0x22 */
+ { NULL, NULL, NULL, NULL, }, /* 0x23 */
+ { NULL, NULL, NULL, NULL, }, /* 0x24 */
+ { NULL, NULL, NULL, NULL, }, /* 0x25 */
+ { NULL, NULL, NULL, NULL, }, /* 0x26 */
+ { &decl_itu_notify, NULL, NULL, NULL, }, /* 0x27 */
+ { NULL, NULL, NULL, NULL, }, /* 0x28 */
+ { NULL, NULL, NULL, NULL, }, /* 0x29 */
+ { NULL, NULL, NULL, NULL, }, /* 0x2a */
+ { NULL, NULL, NULL, NULL, }, /* 0x2b */
+ { NULL, NULL, NULL, NULL, }, /* 0x2c */
+ { NULL, NULL, NULL, NULL, }, /* 0x2d */
+ { NULL, NULL, NULL, NULL, }, /* 0x2e */
+ { NULL, NULL, NULL, NULL, }, /* 0x2f */
+ { NULL, NULL, NULL, NULL, }, /* 0x30 */
+ { NULL, NULL, NULL, NULL, }, /* 0x31 */
+ { NULL, NULL, NULL, NULL, }, /* 0x32 */
+ { NULL, NULL, NULL, NULL, }, /* 0x33 */
+ { NULL, NULL, NULL, NULL, }, /* 0x34 */
+ { NULL, NULL, NULL, NULL, }, /* 0x35 */
+ { NULL, NULL, NULL, NULL, }, /* 0x36 */
+ { NULL, NULL, NULL, NULL, }, /* 0x37 */
+ { NULL, NULL, NULL, NULL, }, /* 0x38 */
+ { NULL, NULL, NULL, NULL, }, /* 0x39 */
+ { NULL, NULL, NULL, NULL, }, /* 0x3a */
+ { NULL, NULL, NULL, NULL, }, /* 0x3b */
+ { NULL, NULL, NULL, NULL, }, /* 0x3c */
+ { NULL, NULL, NULL, NULL, }, /* 0x3d */
+ { NULL, NULL, NULL, NULL, }, /* 0x3e */
+ { NULL, NULL, NULL, NULL, }, /* 0x3f */
+ { NULL, NULL, NULL, NULL, }, /* 0x40 */
+ { NULL, NULL, NULL, NULL, }, /* 0x41 */
+ { &decl_itu_eetd, NULL, NULL, &decl_net_eetd, }, /* 0x42 */
+ { NULL, NULL, NULL, NULL, }, /* 0x43 */
+ { NULL, NULL, NULL, NULL, }, /* 0x44 */
+ { NULL, NULL, NULL, NULL, }, /* 0x45 */
+ { NULL, NULL, NULL, NULL, }, /* 0x46 */
+ { NULL, NULL, NULL, NULL, }, /* 0x47 */
+ { NULL, NULL, NULL, NULL, }, /* 0x48 */
+ { NULL, NULL, NULL, NULL, }, /* 0x49 */
+ { NULL, NULL, NULL, NULL, }, /* 0x4a */
+ { NULL, NULL, NULL, NULL, }, /* 0x4b */
+ { &decl_itu_conned, NULL, NULL, NULL, }, /* 0x4c */
+ { &decl_itu_connedsub, NULL, NULL, NULL, }, /* 0x4d */
+ { NULL, NULL, NULL, NULL, }, /* 0x4e */
+ { NULL, NULL, NULL, NULL, }, /* 0x4f */
+ { NULL, NULL, NULL, NULL, }, /* 0x50 */
+ { NULL, NULL, NULL, NULL, }, /* 0x51 */
+ { NULL, NULL, NULL, NULL, }, /* 0x52 */
+ { NULL, NULL, NULL, NULL, }, /* 0x53 */
+ { &decl_itu_epref, NULL, NULL, NULL, }, /* 0x54 */
+ { &decl_itu_epstate, NULL, NULL, NULL, }, /* 0x55 */
+ { NULL, NULL, NULL, NULL, }, /* 0x56 */
+ { NULL, NULL, NULL, NULL, }, /* 0x57 */
+ { &decl_itu_aal, NULL, NULL, NULL, }, /* 0x58 */
+ { &decl_itu_traffic, NULL, NULL, &decl_net_traffic, }, /* 0x59 */
+ { &decl_itu_connid, NULL, NULL, NULL, }, /* 0x5a */
+ { NULL, NULL, NULL, NULL, }, /* 0x5b */
+ { &decl_itu_qos, NULL, NULL, &decl_net_qos, }, /* 0x5c */
+ { &decl_itu_bhli, NULL, NULL, NULL, }, /* 0x5d */
+ { &decl_itu_bearer, NULL, NULL, NULL, }, /* 0x5e */
+ { &decl_itu_blli, NULL, NULL, NULL, }, /* 0x5f */
+ { &decl_itu_lshift, NULL, NULL, NULL, }, /* 0x60 */
+ { &decl_itu_nlshift, NULL, NULL, NULL, }, /* 0x61 */
+ { &decl_itu_scompl, NULL, NULL, NULL, }, /* 0x62 */
+ { &decl_itu_repeat, NULL, NULL, NULL, }, /* 0x63 */
+ { NULL, NULL, NULL, NULL, }, /* 0x64 */
+ { NULL, NULL, NULL, NULL, }, /* 0x65 */
+ { NULL, NULL, NULL, NULL, }, /* 0x66 */
+ { NULL, NULL, NULL, NULL, }, /* 0x67 */
+ { NULL, NULL, NULL, NULL, }, /* 0x68 */
+ { NULL, NULL, NULL, NULL, }, /* 0x69 */
+ { NULL, NULL, NULL, NULL, }, /* 0x6a */
+ { NULL, NULL, NULL, NULL, }, /* 0x6b */
+ { &decl_itu_calling, NULL, NULL, NULL, }, /* 0x6c */
+ { &decl_itu_callingsub, NULL, NULL, NULL, }, /* 0x6d */
+ { NULL, NULL, NULL, NULL, }, /* 0x6e */
+ { NULL, NULL, NULL, NULL, }, /* 0x6f */
+ { &decl_itu_called, NULL, NULL, NULL, }, /* 0x70 */
+ { &decl_itu_calledsub, NULL, NULL, NULL, }, /* 0x71 */
+ { NULL, NULL, NULL, NULL, }, /* 0x72 */
+ { NULL, NULL, NULL, NULL, }, /* 0x73 */
+ { NULL, NULL, NULL, NULL, }, /* 0x74 */
+ { NULL, NULL, NULL, NULL, }, /* 0x75 */
+ { NULL, NULL, NULL, NULL, }, /* 0x76 */
+ { NULL, NULL, NULL, NULL, }, /* 0x77 */
+ { &decl_itu_tns, NULL, NULL, &decl_net_tns, }, /* 0x78 */
+ { &decl_itu_restart, NULL, NULL, NULL, }, /* 0x79 */
+ { NULL, NULL, NULL, NULL, }, /* 0x7a */
+ { NULL, NULL, NULL, NULL, }, /* 0x7b */
+ { NULL, NULL, NULL, NULL, }, /* 0x7c */
+ { NULL, NULL, NULL, NULL, }, /* 0x7d */
+ { &decl_itu_uu, NULL, NULL, NULL, }, /* 0x7e */
+ { NULL, NULL, NULL, &decl_net_git, }, /* 0x7f */
+ { NULL, NULL, NULL, NULL, }, /* 0x80 */
+ { &decl_itu_mintraffic, NULL, NULL, &decl_net_mintraffic, }, /* 0x81 */
+ { &decl_itu_atraffic, NULL, NULL, &decl_net_atraffic, }, /* 0x82 */
+ { NULL, NULL, NULL, NULL, }, /* 0x83 */
+ { NULL, NULL, NULL, &decl_net_abrsetup, }, /* 0x84 */
+ { NULL, NULL, NULL, NULL, }, /* 0x85 */
+ { NULL, NULL, NULL, NULL, }, /* 0x86 */
+ { NULL, NULL, NULL, NULL, }, /* 0x87 */
+ { NULL, NULL, NULL, NULL, }, /* 0x88 */
+ { &decl_itu_report, NULL, NULL, NULL, }, /* 0x89 */
+ { NULL, NULL, NULL, NULL, }, /* 0x8a */
+ { NULL, NULL, NULL, NULL, }, /* 0x8b */
+ { NULL, NULL, NULL, NULL, }, /* 0x8c */
+ { NULL, NULL, NULL, NULL, }, /* 0x8d */
+ { NULL, NULL, NULL, NULL, }, /* 0x8e */
+ { NULL, NULL, NULL, NULL, }, /* 0x8f */
+ { NULL, NULL, NULL, NULL, }, /* 0x90 */
+ { NULL, NULL, NULL, NULL, }, /* 0x91 */
+ { NULL, NULL, NULL, NULL, }, /* 0x92 */
+ { NULL, NULL, NULL, NULL, }, /* 0x93 */
+ { NULL, NULL, NULL, NULL, }, /* 0x94 */
+ { NULL, NULL, NULL, NULL, }, /* 0x95 */
+ { NULL, NULL, NULL, NULL, }, /* 0x96 */
+ { NULL, NULL, NULL, NULL, }, /* 0x97 */
+ { NULL, NULL, NULL, NULL, }, /* 0x98 */
+ { NULL, NULL, NULL, NULL, }, /* 0x99 */
+ { NULL, NULL, NULL, NULL, }, /* 0x9a */
+ { NULL, NULL, NULL, NULL, }, /* 0x9b */
+ { NULL, NULL, NULL, NULL, }, /* 0x9c */
+ { NULL, NULL, NULL, NULL, }, /* 0x9d */
+ { NULL, NULL, NULL, NULL, }, /* 0x9e */
+ { NULL, NULL, NULL, NULL, }, /* 0x9f */
+ { NULL, NULL, NULL, NULL, }, /* 0xa0 */
+ { NULL, NULL, NULL, NULL, }, /* 0xa1 */
+ { NULL, NULL, NULL, NULL, }, /* 0xa2 */
+ { NULL, NULL, NULL, NULL, }, /* 0xa3 */
+ { NULL, NULL, NULL, NULL, }, /* 0xa4 */
+ { NULL, NULL, NULL, NULL, }, /* 0xa5 */
+ { NULL, NULL, NULL, NULL, }, /* 0xa6 */
+ { NULL, NULL, NULL, NULL, }, /* 0xa7 */
+ { NULL, NULL, NULL, NULL, }, /* 0xa8 */
+ { NULL, NULL, NULL, NULL, }, /* 0xa9 */
+ { NULL, NULL, NULL, NULL, }, /* 0xaa */
+ { NULL, NULL, NULL, NULL, }, /* 0xab */
+ { NULL, NULL, NULL, NULL, }, /* 0xac */
+ { NULL, NULL, NULL, NULL, }, /* 0xad */
+ { NULL, NULL, NULL, NULL, }, /* 0xae */
+ { NULL, NULL, NULL, NULL, }, /* 0xaf */
+ { NULL, NULL, NULL, NULL, }, /* 0xb0 */
+ { NULL, NULL, NULL, NULL, }, /* 0xb1 */
+ { NULL, NULL, NULL, NULL, }, /* 0xb2 */
+ { NULL, NULL, NULL, NULL, }, /* 0xb3 */
+ { NULL, NULL, NULL, NULL, }, /* 0xb4 */
+ { NULL, NULL, NULL, NULL, }, /* 0xb5 */
+ { NULL, NULL, NULL, NULL, }, /* 0xb6 */
+ { NULL, NULL, NULL, NULL, }, /* 0xb7 */
+ { NULL, NULL, NULL, NULL, }, /* 0xb8 */
+ { NULL, NULL, NULL, NULL, }, /* 0xb9 */
+ { NULL, NULL, NULL, NULL, }, /* 0xba */
+ { NULL, NULL, NULL, NULL, }, /* 0xbb */
+ { NULL, NULL, NULL, NULL, }, /* 0xbc */
+ { NULL, NULL, NULL, NULL, }, /* 0xbd */
+ { NULL, NULL, NULL, NULL, }, /* 0xbe */
+ { NULL, NULL, NULL, NULL, }, /* 0xbf */
+ { NULL, NULL, NULL, NULL, }, /* 0xc0 */
+ { NULL, NULL, NULL, NULL, }, /* 0xc1 */
+ { NULL, NULL, NULL, NULL, }, /* 0xc2 */
+ { NULL, NULL, NULL, NULL, }, /* 0xc3 */
+ { NULL, NULL, NULL, NULL, }, /* 0xc4 */
+ { NULL, NULL, NULL, NULL, }, /* 0xc5 */
+ { NULL, NULL, NULL, NULL, }, /* 0xc6 */
+ { NULL, NULL, NULL, NULL, }, /* 0xc7 */
+ { NULL, NULL, NULL, NULL, }, /* 0xc8 */
+ { NULL, NULL, NULL, NULL, }, /* 0xc9 */
+ { NULL, NULL, NULL, NULL, }, /* 0xca */
+ { NULL, NULL, NULL, NULL, }, /* 0xcb */
+ { NULL, NULL, NULL, NULL, }, /* 0xcc */
+ { NULL, NULL, NULL, NULL, }, /* 0xcd */
+ { NULL, NULL, NULL, NULL, }, /* 0xce */
+ { NULL, NULL, NULL, NULL, }, /* 0xcf */
+ { NULL, NULL, NULL, NULL, }, /* 0xd0 */
+ { NULL, NULL, NULL, NULL, }, /* 0xd1 */
+ { NULL, NULL, NULL, NULL, }, /* 0xd2 */
+ { NULL, NULL, NULL, NULL, }, /* 0xd3 */
+ { NULL, NULL, NULL, NULL, }, /* 0xd4 */
+ { NULL, NULL, NULL, NULL, }, /* 0xd5 */
+ { NULL, NULL, NULL, NULL, }, /* 0xd6 */
+ { NULL, NULL, NULL, NULL, }, /* 0xd7 */
+ { NULL, NULL, NULL, NULL, }, /* 0xd8 */
+ { NULL, NULL, NULL, NULL, }, /* 0xd9 */
+ { NULL, NULL, NULL, NULL, }, /* 0xda */
+ { NULL, NULL, NULL, NULL, }, /* 0xdb */
+ { NULL, NULL, NULL, NULL, }, /* 0xdc */
+ { NULL, NULL, NULL, NULL, }, /* 0xdd */
+ { NULL, NULL, NULL, NULL, }, /* 0xde */
+ { NULL, NULL, NULL, NULL, }, /* 0xdf */
+ { NULL, NULL, NULL, &decl_net_called_soft, }, /* 0xe0 */
+ { NULL, NULL, NULL, &decl_net_crankback, }, /* 0xe1 */
+ { NULL, NULL, NULL, &decl_net_dtl, }, /* 0xe2 */
+ { NULL, NULL, NULL, &decl_net_calling_soft, }, /* 0xe3 */
+ { NULL, NULL, NULL, &decl_net_abradd, }, /* 0xe4 */
+ { NULL, NULL, NULL, NULL, }, /* 0xe5 */
+ { NULL, NULL, NULL, NULL, }, /* 0xe6 */
+ { NULL, NULL, NULL, NULL, }, /* 0xe7 */
+ { NULL, NULL, NULL, &decl_net_lij_callid, }, /* 0xe8 */
+ { NULL, NULL, NULL, &decl_net_lij_param, }, /* 0xe9 */
+ { NULL, NULL, NULL, &decl_net_lij_seqno, }, /* 0xea */
+ { NULL, NULL, NULL, &decl_net_cscope, }, /* 0xeb */
+ { NULL, NULL, NULL, &decl_net_exqos, }, /* 0xec */
+ { NULL, NULL, NULL, NULL, }, /* 0xed */
+ { NULL, NULL, NULL, NULL, }, /* 0xee */
+ { NULL, NULL, NULL, NULL, }, /* 0xef */
+ { NULL, NULL, NULL, &decl_net_mdcr, }, /* 0xf0 */
+ { NULL, NULL, NULL, NULL, }, /* 0xf1 */
+ { NULL, NULL, NULL, NULL, }, /* 0xf2 */
+ { NULL, NULL, NULL, NULL, }, /* 0xf3 */
+ { NULL, NULL, NULL, NULL, }, /* 0xf4 */
+ { NULL, NULL, NULL, NULL, }, /* 0xf5 */
+ { NULL, NULL, NULL, NULL, }, /* 0xf6 */
+ { NULL, NULL, NULL, NULL, }, /* 0xf7 */
+ { NULL, NULL, NULL, NULL, }, /* 0xf8 */
+ { NULL, NULL, NULL, NULL, }, /* 0xf9 */
+ { NULL, NULL, NULL, NULL, }, /* 0xfa */
+ { NULL, NULL, NULL, NULL, }, /* 0xfb */
+ { NULL, NULL, NULL, NULL, }, /* 0xfc */
+ { NULL, NULL, NULL, NULL, }, /* 0xfd */
+ { &decl_itu_unrec, NULL, NULL, NULL, }, /* 0xfe */
+ { NULL, NULL, NULL, NULL, }, /* 0xff */
+};
diff --git a/sys/contrib/ngatm/netnatm/msg/uni_msg.c b/sys/contrib/ngatm/netnatm/msg/uni_msg.c
new file mode 100644
index 000000000000..f9991858b418
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uni_msg.c
@@ -0,0 +1,4901 @@
+/* This file was created automatically
+ * Source file: $Begemot: libunimsg/atm/msg/msg.def,v 1.3 2003/09/19 11:58:15 hbb Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef _KERNEL
+#include <sys/libkern.h>
+#else
+#include <string.h>
+#endif
+#include <netnatm/unimsg.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/msg/priv.h>
+#include <netnatm/msg/privmsg.c>
+
+static void
+print_alerting(struct uni_alerting *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->connid.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNID, (union uni_ieall *)&msg->connid, cx);
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ if(msg->report.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_REPORT, (union uni_ieall *)&msg->report, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_alerting(struct uni_alerting *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->connid);
+ else
+ ret |= uni_check_ie(UNI_IE_CONNID, (union uni_ieall *)&m->connid, cx);
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->report);
+ else
+ ret |= uni_check_ie(UNI_IE_REPORT, (union uni_ieall *)&m->report, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_alerting(struct uni_msg *msg, struct uni_alerting *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_ALERTING, cx, &mlen))
+ return (-2);
+
+ if((p->connid.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNID, msg, (union uni_ieall *)&p->connid, cx))
+ return (UNI_IE_CONNID);
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ if((p->report.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_REPORT, msg, (union uni_ieall *)&p->report, cx))
+ return (UNI_IE_REPORT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_alerting(struct uni_alerting *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_CONNID:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->connid.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNID, (union uni_ieall *)&out->connid, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_REPORT:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->report.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_REPORT, (union uni_ieall *)&out->report, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_alerting = {
+ 0,
+ "alerting",
+ (uni_msg_print_f)print_alerting,
+ (uni_msg_check_f)check_alerting,
+ (uni_msg_encode_f)encode_alerting,
+ (uni_msg_decode_f)decode_alerting
+};
+
+static void
+print_call_proc(struct uni_call_proc *msg, struct unicx *cx)
+{
+ if(msg->connid.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNID, (union uni_ieall *)&msg->connid, cx);
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_call_proc(struct uni_call_proc *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_CONNID, (union uni_ieall *)&m->connid, cx);
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->notify);
+ else
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_call_proc(struct uni_msg *msg, struct uni_call_proc *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_CALL_PROC, cx, &mlen))
+ return (-2);
+
+ if((p->connid.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNID, msg, (union uni_ieall *)&p->connid, cx))
+ return (UNI_IE_CONNID);
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_call_proc(struct uni_call_proc *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_CONNID:
+ out->connid.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNID, (union uni_ieall *)&out->connid, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_call_proc = {
+ 0,
+ "call_proc",
+ (uni_msg_print_f)print_call_proc,
+ (uni_msg_check_f)check_call_proc,
+ (uni_msg_encode_f)encode_call_proc,
+ (uni_msg_decode_f)decode_call_proc
+};
+
+static void
+print_connect(struct uni_connect *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->aal.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_AAL, (union uni_ieall *)&msg->aal, cx);
+ if(msg->blli.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_BLLI, (union uni_ieall *)&msg->blli, cx);
+ if(msg->connid.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNID, (union uni_ieall *)&msg->connid, cx);
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->conned.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNED, (union uni_ieall *)&msg->conned, cx);
+ if(msg->connedsub.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNEDSUB, (union uni_ieall *)&msg->connedsub, cx);
+ if(msg->eetd.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EETD, (union uni_ieall *)&msg->eetd, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ if(msg->traffic.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_TRAFFIC, (union uni_ieall *)&msg->traffic, cx);
+ if(msg->exqos.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EXQOS, (union uni_ieall *)&msg->exqos, cx);
+ if(msg->facility.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_FACILITY, (union uni_ieall *)&msg->facility, cx);
+ if(msg->abrsetup.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_ABRSETUP, (union uni_ieall *)&msg->abrsetup, cx);
+ if(msg->abradd.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_ABRADD, (union uni_ieall *)&msg->abradd, cx);
+ if(msg->called_soft.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED_SOFT, (union uni_ieall *)&msg->called_soft, cx);
+ if(msg->report.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_REPORT, (union uni_ieall *)&msg->report, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_connect(struct uni_connect *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_AAL, (union uni_ieall *)&m->aal, cx);
+ ret |= uni_check_ie(UNI_IE_BLLI, (union uni_ieall *)&m->blli, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->connid);
+ else
+ ret |= uni_check_ie(UNI_IE_CONNID, (union uni_ieall *)&m->connid, cx);
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ ret |= uni_check_ie(UNI_IE_CONNED, (union uni_ieall *)&m->conned, cx);
+ ret |= uni_check_ie(UNI_IE_CONNEDSUB, (union uni_ieall *)&m->connedsub, cx);
+ ret |= uni_check_ie(UNI_IE_EETD, (union uni_ieall *)&m->eetd, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ ret |= uni_check_ie(UNI_IE_TRAFFIC, (union uni_ieall *)&m->traffic, cx);
+ ret |= uni_check_ie(UNI_IE_EXQOS, (union uni_ieall *)&m->exqos, cx);
+ if(!(cx->q2932))
+ ret |= IE_ISPRESENT(m->facility);
+ else
+ ret |= uni_check_ie(UNI_IE_FACILITY, (union uni_ieall *)&m->facility, cx);
+ ret |= uni_check_ie(UNI_IE_ABRSETUP, (union uni_ieall *)&m->abrsetup, cx);
+ ret |= uni_check_ie(UNI_IE_ABRADD, (union uni_ieall *)&m->abradd, cx);
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->called_soft);
+ else
+ ret |= uni_check_ie(UNI_IE_CALLED_SOFT, (union uni_ieall *)&m->called_soft, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->report);
+ else
+ ret |= uni_check_ie(UNI_IE_REPORT, (union uni_ieall *)&m->report, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_connect(struct uni_msg *msg, struct uni_connect *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_CONNECT, cx, &mlen))
+ return (-2);
+
+ if((p->aal.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_AAL, msg, (union uni_ieall *)&p->aal, cx))
+ return (UNI_IE_AAL);
+ if((p->blli.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_BLLI, msg, (union uni_ieall *)&p->blli, cx))
+ return (UNI_IE_BLLI);
+ if((p->connid.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNID, msg, (union uni_ieall *)&p->connid, cx))
+ return (UNI_IE_CONNID);
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->conned.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNED, msg, (union uni_ieall *)&p->conned, cx))
+ return (UNI_IE_CONNED);
+ if((p->connedsub.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNEDSUB, msg, (union uni_ieall *)&p->connedsub, cx))
+ return (UNI_IE_CONNEDSUB);
+ if((p->eetd.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EETD, msg, (union uni_ieall *)&p->eetd, cx))
+ return (UNI_IE_EETD);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ if((p->traffic.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_TRAFFIC, msg, (union uni_ieall *)&p->traffic, cx))
+ return (UNI_IE_TRAFFIC);
+ if((p->exqos.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EXQOS, msg, (union uni_ieall *)&p->exqos, cx))
+ return (UNI_IE_EXQOS);
+ if((p->facility.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_FACILITY, msg, (union uni_ieall *)&p->facility, cx))
+ return (UNI_IE_FACILITY);
+ if((p->abrsetup.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_ABRSETUP, msg, (union uni_ieall *)&p->abrsetup, cx))
+ return (UNI_IE_ABRSETUP);
+ if((p->abradd.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_ABRADD, msg, (union uni_ieall *)&p->abradd, cx))
+ return (UNI_IE_ABRADD);
+ if((p->called_soft.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED_SOFT, msg, (union uni_ieall *)&p->called_soft, cx))
+ return (UNI_IE_CALLED_SOFT);
+ if((p->report.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_REPORT, msg, (union uni_ieall *)&p->report, cx))
+ return (UNI_IE_REPORT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_connect(struct uni_connect *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_AAL:
+ out->aal.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_AAL, (union uni_ieall *)&out->aal, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_BLLI:
+ out->blli.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_BLLI, (union uni_ieall *)&out->blli, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CONNID:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->connid.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNID, (union uni_ieall *)&out->connid, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CONNED:
+ out->conned.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNED, (union uni_ieall *)&out->conned, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CONNEDSUB:
+ out->connedsub.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNEDSUB, (union uni_ieall *)&out->connedsub, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EETD:
+ out->eetd.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EETD, (union uni_ieall *)&out->eetd, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_TRAFFIC:
+ out->traffic.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_TRAFFIC, (union uni_ieall *)&out->traffic, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EXQOS:
+ out->exqos.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EXQOS, (union uni_ieall *)&out->exqos, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_FACILITY:
+ if (!(cx->q2932))
+ return (DEC_ILL);
+ out->facility.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_FACILITY, (union uni_ieall *)&out->facility, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_ABRSETUP:
+ out->abrsetup.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_ABRSETUP, (union uni_ieall *)&out->abrsetup, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_ABRADD:
+ out->abradd.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_ABRADD, (union uni_ieall *)&out->abradd, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLED_SOFT:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ out->called_soft.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED_SOFT, (union uni_ieall *)&out->called_soft, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_REPORT:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->report.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_REPORT, (union uni_ieall *)&out->report, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_connect = {
+ 0,
+ "connect",
+ (uni_msg_print_f)print_connect,
+ (uni_msg_check_f)check_connect,
+ (uni_msg_encode_f)encode_connect,
+ (uni_msg_decode_f)decode_connect
+};
+
+static void
+print_connect_ack(struct uni_connect_ack *msg, struct unicx *cx)
+{
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_connect_ack(struct uni_connect_ack *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_connect_ack(struct uni_msg *msg, struct uni_connect_ack *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_CONNECT_ACK, cx, &mlen))
+ return (-2);
+
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_connect_ack(struct uni_connect_ack *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_connect_ack = {
+ 0,
+ "connect_ack",
+ (uni_msg_print_f)print_connect_ack,
+ (uni_msg_check_f)check_connect_ack,
+ (uni_msg_encode_f)encode_connect_ack,
+ (uni_msg_decode_f)decode_connect_ack
+};
+
+static void
+print_release(struct uni_release *msg, struct unicx *cx)
+{
+ u_int i;
+
+ for(i = 0; i < 2; i++)
+ if(msg->cause[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CAUSE, (union uni_ieall *)&msg->cause[i], cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ if(msg->facility.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_FACILITY, (union uni_ieall *)&msg->facility, cx);
+ if(msg->crankback.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CRANKBACK, (union uni_ieall *)&msg->crankback, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_release(struct uni_release *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ for(i = 0; i < 2 ; i++) {
+ ret |= uni_check_ie(UNI_IE_CAUSE, (union uni_ieall *)&m->cause[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ if(!(cx->q2932))
+ ret |= IE_ISPRESENT(m->facility);
+ else
+ ret |= uni_check_ie(UNI_IE_FACILITY, (union uni_ieall *)&m->facility, cx);
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->crankback);
+ else
+ ret |= uni_check_ie(UNI_IE_CRANKBACK, (union uni_ieall *)&m->crankback, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_release(struct uni_msg *msg, struct uni_release *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_RELEASE, cx, &mlen))
+ return (-2);
+
+ for(i = 0; i < 2; i++)
+ if((p->cause[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CAUSE, msg, (union uni_ieall *)&p->cause[i], cx))
+ return ((i << 16) + UNI_IE_CAUSE);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ if((p->facility.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_FACILITY, msg, (union uni_ieall *)&p->facility, cx))
+ return (UNI_IE_FACILITY);
+ if((p->crankback.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CRANKBACK, msg, (union uni_ieall *)&p->crankback, cx))
+ return (UNI_IE_CRANKBACK);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_release(struct uni_release *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_CAUSE:
+ for(i = 0; i < 2; i++)
+ if (!IE_ISPRESENT(out->cause[i])) {
+ out->cause[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CAUSE, (union uni_ieall *)&out->cause[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_FACILITY:
+ if (!(cx->q2932))
+ return (DEC_ILL);
+ out->facility.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_FACILITY, (union uni_ieall *)&out->facility, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CRANKBACK:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ out->crankback.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CRANKBACK, (union uni_ieall *)&out->crankback, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_release = {
+ 0,
+ "release",
+ (uni_msg_print_f)print_release,
+ (uni_msg_check_f)check_release,
+ (uni_msg_encode_f)encode_release,
+ (uni_msg_decode_f)decode_release
+};
+
+static void
+print_release_compl(struct uni_release_compl *msg, struct unicx *cx)
+{
+ u_int i;
+
+ for(i = 0; i < 2; i++)
+ if(msg->cause[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CAUSE, (union uni_ieall *)&msg->cause[i], cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ if(msg->crankback.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CRANKBACK, (union uni_ieall *)&msg->crankback, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_release_compl(struct uni_release_compl *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ for(i = 0; i < 2 ; i++) {
+ ret |= uni_check_ie(UNI_IE_CAUSE, (union uni_ieall *)&m->cause[i], cx);
+ }
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->git[i]);
+ else
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->crankback);
+ else
+ ret |= uni_check_ie(UNI_IE_CRANKBACK, (union uni_ieall *)&m->crankback, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_release_compl(struct uni_msg *msg, struct uni_release_compl *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_RELEASE_COMPL, cx, &mlen))
+ return (-2);
+
+ for(i = 0; i < 2; i++)
+ if((p->cause[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CAUSE, msg, (union uni_ieall *)&p->cause[i], cx))
+ return ((i << 16) + UNI_IE_CAUSE);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ if((p->crankback.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CRANKBACK, msg, (union uni_ieall *)&p->crankback, cx))
+ return (UNI_IE_CRANKBACK);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_release_compl(struct uni_release_compl *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_CAUSE:
+ for(i = 0; i < 2; i++)
+ if (!IE_ISPRESENT(out->cause[i])) {
+ out->cause[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CAUSE, (union uni_ieall *)&out->cause[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_GIT:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CRANKBACK:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ out->crankback.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CRANKBACK, (union uni_ieall *)&out->crankback, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_release_compl = {
+ 0,
+ "release_compl",
+ (uni_msg_print_f)print_release_compl,
+ (uni_msg_check_f)check_release_compl,
+ (uni_msg_encode_f)encode_release_compl,
+ (uni_msg_decode_f)decode_release_compl
+};
+
+static void
+print_setup(struct uni_setup *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->aal.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_AAL, (union uni_ieall *)&msg->aal, cx);
+ if(msg->traffic.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_TRAFFIC, (union uni_ieall *)&msg->traffic, cx);
+ if(msg->bearer.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_BEARER, (union uni_ieall *)&msg->bearer, cx);
+ if(msg->bhli.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_BHLI, (union uni_ieall *)&msg->bhli, cx);
+ if(msg->blli_repeat.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_REPEAT, (union uni_ieall *)&msg->blli_repeat, cx);
+ for(i = 0; i < UNI_NUM_IE_BLLI; i++)
+ if(msg->blli[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_BLLI, (union uni_ieall *)&msg->blli[i], cx);
+ if(msg->called.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&msg->called, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB; i++)
+ if(msg->calledsub[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLEDSUB, (union uni_ieall *)&msg->calledsub[i], cx);
+ if(msg->calling.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLING, (union uni_ieall *)&msg->calling, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB; i++)
+ if(msg->callingsub[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLINGSUB, (union uni_ieall *)&msg->callingsub[i], cx);
+ if(msg->connid.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNID, (union uni_ieall *)&msg->connid, cx);
+ if(msg->qos.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_QOS, (union uni_ieall *)&msg->qos, cx);
+ if(msg->eetd.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EETD, (union uni_ieall *)&msg->eetd, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->scompl.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_SCOMPL, (union uni_ieall *)&msg->scompl, cx);
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if(msg->tns[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_TNS, (union uni_ieall *)&msg->tns[i], cx);
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->atraffic.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_ATRAFFIC, (union uni_ieall *)&msg->atraffic, cx);
+ if(msg->mintraffic.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_MINTRAFFIC, (union uni_ieall *)&msg->mintraffic, cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->lij_callid.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_LIJ_CALLID, (union uni_ieall *)&msg->lij_callid, cx);
+ if(msg->lij_param.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_LIJ_PARAM, (union uni_ieall *)&msg->lij_param, cx);
+ if(msg->lij_seqno.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&msg->lij_seqno, cx);
+ if(msg->exqos.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EXQOS, (union uni_ieall *)&msg->exqos, cx);
+ if(msg->abrsetup.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_ABRSETUP, (union uni_ieall *)&msg->abrsetup, cx);
+ if(msg->abradd.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_ABRADD, (union uni_ieall *)&msg->abradd, cx);
+ if(msg->cscope.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CSCOPE, (union uni_ieall *)&msg->cscope, cx);
+ if(msg->calling_soft.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLING_SOFT, (union uni_ieall *)&msg->calling_soft, cx);
+ if(msg->called_soft.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED_SOFT, (union uni_ieall *)&msg->called_soft, cx);
+ if(msg->dtl_repeat.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_REPEAT, (union uni_ieall *)&msg->dtl_repeat, cx);
+ for(i = 0; i < UNI_NUM_IE_DTL; i++)
+ if(msg->dtl[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_DTL, (union uni_ieall *)&msg->dtl[i], cx);
+ if(msg->report.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_REPORT, (union uni_ieall *)&msg->report, cx);
+ if(msg->mdcr.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_MDCR, (union uni_ieall *)&msg->mdcr, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_setup(struct uni_setup *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_AAL, (union uni_ieall *)&m->aal, cx);
+ ret |= uni_check_ie(UNI_IE_TRAFFIC, (union uni_ieall *)&m->traffic, cx);
+ ret |= uni_check_ie(UNI_IE_BEARER, (union uni_ieall *)&m->bearer, cx);
+ ret |= uni_check_ie(UNI_IE_BHLI, (union uni_ieall *)&m->bhli, cx);
+ ret |= uni_check_ie(UNI_IE_REPEAT, (union uni_ieall *)&m->blli_repeat, cx);
+ for(i = 0; i < UNI_NUM_IE_BLLI ; i++) {
+ ret |= uni_check_ie(UNI_IE_BLLI, (union uni_ieall *)&m->blli[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&m->called, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB ; i++) {
+ ret |= uni_check_ie(UNI_IE_CALLEDSUB, (union uni_ieall *)&m->calledsub[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_CALLING, (union uni_ieall *)&m->calling, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB ; i++) {
+ ret |= uni_check_ie(UNI_IE_CALLINGSUB, (union uni_ieall *)&m->callingsub[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_CONNID, (union uni_ieall *)&m->connid, cx);
+ ret |= uni_check_ie(UNI_IE_QOS, (union uni_ieall *)&m->qos, cx);
+ ret |= uni_check_ie(UNI_IE_EETD, (union uni_ieall *)&m->eetd, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->scompl);
+ else
+ ret |= uni_check_ie(UNI_IE_SCOMPL, (union uni_ieall *)&m->scompl, cx);
+ for(i = 0; i < UNI_NUM_IE_TNS ; i++) {
+ ret |= uni_check_ie(UNI_IE_TNS, (union uni_ieall *)&m->tns[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_ATRAFFIC, (union uni_ieall *)&m->atraffic, cx);
+ ret |= uni_check_ie(UNI_IE_MINTRAFFIC, (union uni_ieall *)&m->mintraffic, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->lij_callid);
+ else
+ ret |= uni_check_ie(UNI_IE_LIJ_CALLID, (union uni_ieall *)&m->lij_callid, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->lij_param);
+ else
+ ret |= uni_check_ie(UNI_IE_LIJ_PARAM, (union uni_ieall *)&m->lij_param, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->lij_seqno);
+ else
+ ret |= uni_check_ie(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&m->lij_seqno, cx);
+ ret |= uni_check_ie(UNI_IE_EXQOS, (union uni_ieall *)&m->exqos, cx);
+ ret |= uni_check_ie(UNI_IE_ABRSETUP, (union uni_ieall *)&m->abrsetup, cx);
+ ret |= uni_check_ie(UNI_IE_ABRADD, (union uni_ieall *)&m->abradd, cx);
+ ret |= uni_check_ie(UNI_IE_CSCOPE, (union uni_ieall *)&m->cscope, cx);
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->calling_soft);
+ else
+ ret |= uni_check_ie(UNI_IE_CALLING_SOFT, (union uni_ieall *)&m->calling_soft, cx);
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->called_soft);
+ else
+ ret |= uni_check_ie(UNI_IE_CALLED_SOFT, (union uni_ieall *)&m->called_soft, cx);
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->dtl_repeat);
+ else
+ ret |= uni_check_ie(UNI_IE_REPEAT, (union uni_ieall *)&m->dtl_repeat, cx);
+ for(i = 0; i < UNI_NUM_IE_DTL ; i++) {
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->dtl[i]);
+ else
+ ret |= uni_check_ie(UNI_IE_DTL, (union uni_ieall *)&m->dtl[i], cx);
+ }
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->report);
+ else
+ ret |= uni_check_ie(UNI_IE_REPORT, (union uni_ieall *)&m->report, cx);
+ ret |= uni_check_ie(UNI_IE_MDCR, (union uni_ieall *)&m->mdcr, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_setup(struct uni_msg *msg, struct uni_setup *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_SETUP, cx, &mlen))
+ return (-2);
+
+ if((p->aal.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_AAL, msg, (union uni_ieall *)&p->aal, cx))
+ return (UNI_IE_AAL);
+ if((p->traffic.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_TRAFFIC, msg, (union uni_ieall *)&p->traffic, cx))
+ return (UNI_IE_TRAFFIC);
+ if((p->bearer.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_BEARER, msg, (union uni_ieall *)&p->bearer, cx))
+ return (UNI_IE_BEARER);
+ if((p->bhli.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_BHLI, msg, (union uni_ieall *)&p->bhli, cx))
+ return (UNI_IE_BHLI);
+ if((p->blli_repeat.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_BLLI, msg, (union uni_ieall *)&p->blli_repeat, cx))
+ return (0x10000000 + UNI_IE_BLLI);
+ for(i = 0; i < UNI_NUM_IE_BLLI; i++)
+ if((p->blli[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_BLLI, msg, (union uni_ieall *)&p->blli[i], cx))
+ return ((i << 16) + UNI_IE_BLLI);
+ if((p->called.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED, msg, (union uni_ieall *)&p->called, cx))
+ return (UNI_IE_CALLED);
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB; i++)
+ if((p->calledsub[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLEDSUB, msg, (union uni_ieall *)&p->calledsub[i], cx))
+ return ((i << 16) + UNI_IE_CALLEDSUB);
+ if((p->calling.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLING, msg, (union uni_ieall *)&p->calling, cx))
+ return (UNI_IE_CALLING);
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB; i++)
+ if((p->callingsub[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLINGSUB, msg, (union uni_ieall *)&p->callingsub[i], cx))
+ return ((i << 16) + UNI_IE_CALLINGSUB);
+ if((p->connid.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNID, msg, (union uni_ieall *)&p->connid, cx))
+ return (UNI_IE_CONNID);
+ if((p->qos.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_QOS, msg, (union uni_ieall *)&p->qos, cx))
+ return (UNI_IE_QOS);
+ if((p->eetd.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EETD, msg, (union uni_ieall *)&p->eetd, cx))
+ return (UNI_IE_EETD);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->scompl.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_SCOMPL, msg, (union uni_ieall *)&p->scompl, cx))
+ return (UNI_IE_SCOMPL);
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if((p->tns[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_TNS, msg, (union uni_ieall *)&p->tns[i], cx))
+ return ((i << 16) + UNI_IE_TNS);
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->atraffic.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_ATRAFFIC, msg, (union uni_ieall *)&p->atraffic, cx))
+ return (UNI_IE_ATRAFFIC);
+ if((p->mintraffic.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_MINTRAFFIC, msg, (union uni_ieall *)&p->mintraffic, cx))
+ return (UNI_IE_MINTRAFFIC);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->lij_callid.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_LIJ_CALLID, msg, (union uni_ieall *)&p->lij_callid, cx))
+ return (UNI_IE_LIJ_CALLID);
+ if((p->lij_param.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_LIJ_PARAM, msg, (union uni_ieall *)&p->lij_param, cx))
+ return (UNI_IE_LIJ_PARAM);
+ if((p->lij_seqno.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_LIJ_SEQNO, msg, (union uni_ieall *)&p->lij_seqno, cx))
+ return (UNI_IE_LIJ_SEQNO);
+ if((p->exqos.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EXQOS, msg, (union uni_ieall *)&p->exqos, cx))
+ return (UNI_IE_EXQOS);
+ if((p->abrsetup.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_ABRSETUP, msg, (union uni_ieall *)&p->abrsetup, cx))
+ return (UNI_IE_ABRSETUP);
+ if((p->abradd.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_ABRADD, msg, (union uni_ieall *)&p->abradd, cx))
+ return (UNI_IE_ABRADD);
+ if((p->cscope.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CSCOPE, msg, (union uni_ieall *)&p->cscope, cx))
+ return (UNI_IE_CSCOPE);
+ if((p->calling_soft.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLING_SOFT, msg, (union uni_ieall *)&p->calling_soft, cx))
+ return (UNI_IE_CALLING_SOFT);
+ if((p->called_soft.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED_SOFT, msg, (union uni_ieall *)&p->called_soft, cx))
+ return (UNI_IE_CALLED_SOFT);
+ if((p->dtl_repeat.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_DTL, msg, (union uni_ieall *)&p->dtl_repeat, cx))
+ return (0x10000000 + UNI_IE_DTL);
+ for(i = 0; i < UNI_NUM_IE_DTL; i++)
+ if((p->dtl[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_DTL, msg, (union uni_ieall *)&p->dtl[i], cx))
+ return ((i << 16) + UNI_IE_DTL);
+ if((p->report.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_REPORT, msg, (union uni_ieall *)&p->report, cx))
+ return (UNI_IE_REPORT);
+ if((p->mdcr.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_MDCR, msg, (union uni_ieall *)&p->mdcr, cx))
+ return (UNI_IE_MDCR);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_setup(struct uni_setup *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_AAL:
+ out->aal.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_AAL, (union uni_ieall *)&out->aal, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_TRAFFIC:
+ out->traffic.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_TRAFFIC, (union uni_ieall *)&out->traffic, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_BEARER:
+ out->bearer.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_BEARER, (union uni_ieall *)&out->bearer, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_BHLI:
+ out->bhli.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_BHLI, (union uni_ieall *)&out->bhli, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_BLLI:
+ if (IE_ISPRESENT(cx->repeat))
+ out->blli_repeat = cx->repeat;
+ for(i = 0; i < UNI_NUM_IE_BLLI; i++)
+ if (!IE_ISPRESENT(out->blli[i])) {
+ out->blli[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_BLLI, (union uni_ieall *)&out->blli[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_CALLED:
+ out->called.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED, (union uni_ieall *)&out->called, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLEDSUB:
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB; i++)
+ if (!IE_ISPRESENT(out->calledsub[i])) {
+ out->calledsub[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLEDSUB, (union uni_ieall *)&out->calledsub[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_CALLING:
+ out->calling.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLING, (union uni_ieall *)&out->calling, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLINGSUB:
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB; i++)
+ if (!IE_ISPRESENT(out->callingsub[i])) {
+ out->callingsub[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLINGSUB, (union uni_ieall *)&out->callingsub[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_CONNID:
+ out->connid.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNID, (union uni_ieall *)&out->connid, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_QOS:
+ out->qos.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_QOS, (union uni_ieall *)&out->qos, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EETD:
+ out->eetd.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EETD, (union uni_ieall *)&out->eetd, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_SCOMPL:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->scompl.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_SCOMPL, (union uni_ieall *)&out->scompl, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_TNS:
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if (!IE_ISPRESENT(out->tns[i])) {
+ out->tns[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_TNS, (union uni_ieall *)&out->tns[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_ATRAFFIC:
+ out->atraffic.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_ATRAFFIC, (union uni_ieall *)&out->atraffic, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_MINTRAFFIC:
+ out->mintraffic.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_MINTRAFFIC, (union uni_ieall *)&out->mintraffic, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_LIJ_CALLID:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->lij_callid.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_LIJ_CALLID, (union uni_ieall *)&out->lij_callid, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_LIJ_PARAM:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->lij_param.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_LIJ_PARAM, (union uni_ieall *)&out->lij_param, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_LIJ_SEQNO:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->lij_seqno.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&out->lij_seqno, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EXQOS:
+ out->exqos.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EXQOS, (union uni_ieall *)&out->exqos, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_ABRSETUP:
+ out->abrsetup.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_ABRSETUP, (union uni_ieall *)&out->abrsetup, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_ABRADD:
+ out->abradd.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_ABRADD, (union uni_ieall *)&out->abradd, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CSCOPE:
+ out->cscope.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CSCOPE, (union uni_ieall *)&out->cscope, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLING_SOFT:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ out->calling_soft.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLING_SOFT, (union uni_ieall *)&out->calling_soft, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLED_SOFT:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ out->called_soft.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED_SOFT, (union uni_ieall *)&out->called_soft, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_DTL:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ if (IE_ISPRESENT(cx->repeat))
+ out->dtl_repeat = cx->repeat;
+ for(i = 0; i < UNI_NUM_IE_DTL; i++)
+ if (!IE_ISPRESENT(out->dtl[i])) {
+ out->dtl[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_DTL, (union uni_ieall *)&out->dtl[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_REPORT:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->report.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_REPORT, (union uni_ieall *)&out->report, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_MDCR:
+ out->mdcr.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_MDCR, (union uni_ieall *)&out->mdcr, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_REPEAT:
+ cx->repeat.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if (uni_decode_ie_body(UNI_IE_REPEAT, (union uni_ieall *)&cx->repeat, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_setup = {
+ 0,
+ "setup",
+ (uni_msg_print_f)print_setup,
+ (uni_msg_check_f)check_setup,
+ (uni_msg_encode_f)encode_setup,
+ (uni_msg_decode_f)decode_setup
+};
+
+static void
+print_status(struct uni_status *msg, struct unicx *cx)
+{
+ if(msg->callstate.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLSTATE, (union uni_ieall *)&msg->callstate, cx);
+ if(msg->cause.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CAUSE, (union uni_ieall *)&msg->cause, cx);
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->epstate.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPSTATE, (union uni_ieall *)&msg->epstate, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_status(struct uni_status *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_CALLSTATE, (union uni_ieall *)&m->callstate, cx);
+ ret |= uni_check_ie(UNI_IE_CAUSE, (union uni_ieall *)&m->cause, cx);
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_EPSTATE, (union uni_ieall *)&m->epstate, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_status(struct uni_msg *msg, struct uni_status *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_STATUS, cx, &mlen))
+ return (-2);
+
+ if((p->callstate.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLSTATE, msg, (union uni_ieall *)&p->callstate, cx))
+ return (UNI_IE_CALLSTATE);
+ if((p->cause.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CAUSE, msg, (union uni_ieall *)&p->cause, cx))
+ return (UNI_IE_CAUSE);
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->epstate.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPSTATE, msg, (union uni_ieall *)&p->epstate, cx))
+ return (UNI_IE_EPSTATE);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_status(struct uni_status *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_CALLSTATE:
+ out->callstate.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLSTATE, (union uni_ieall *)&out->callstate, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CAUSE:
+ out->cause.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CAUSE, (union uni_ieall *)&out->cause, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EPSTATE:
+ out->epstate.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPSTATE, (union uni_ieall *)&out->epstate, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_status = {
+ 0,
+ "status",
+ (uni_msg_print_f)print_status,
+ (uni_msg_check_f)check_status,
+ (uni_msg_encode_f)encode_status,
+ (uni_msg_decode_f)decode_status
+};
+
+static void
+print_status_enq(struct uni_status_enq *msg, struct unicx *cx)
+{
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_status_enq(struct uni_status_enq *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_status_enq(struct uni_msg *msg, struct uni_status_enq *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_STATUS_ENQ, cx, &mlen))
+ return (-2);
+
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_status_enq(struct uni_status_enq *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_status_enq = {
+ 0,
+ "status_enq",
+ (uni_msg_print_f)print_status_enq,
+ (uni_msg_check_f)check_status_enq,
+ (uni_msg_encode_f)encode_status_enq,
+ (uni_msg_decode_f)decode_status_enq
+};
+
+static void
+print_notify(struct uni_notify *msg, struct unicx *cx)
+{
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_notify(struct uni_notify *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_notify(struct uni_msg *msg, struct uni_notify *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_NOTIFY, cx, &mlen))
+ return (-2);
+
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_notify(struct uni_notify *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_notify = {
+ 0,
+ "notify",
+ (uni_msg_print_f)print_notify,
+ (uni_msg_check_f)check_notify,
+ (uni_msg_encode_f)encode_notify,
+ (uni_msg_decode_f)decode_notify
+};
+
+static void
+print_restart(struct uni_restart *msg, struct unicx *cx)
+{
+ if(msg->connid.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNID, (union uni_ieall *)&msg->connid, cx);
+ if(msg->restart.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_RESTART, (union uni_ieall *)&msg->restart, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_restart(struct uni_restart *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_CONNID, (union uni_ieall *)&m->connid, cx);
+ ret |= uni_check_ie(UNI_IE_RESTART, (union uni_ieall *)&m->restart, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_restart(struct uni_msg *msg, struct uni_restart *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_RESTART, cx, &mlen))
+ return (-2);
+
+ if((p->connid.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNID, msg, (union uni_ieall *)&p->connid, cx))
+ return (UNI_IE_CONNID);
+ if((p->restart.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_RESTART, msg, (union uni_ieall *)&p->restart, cx))
+ return (UNI_IE_RESTART);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_restart(struct uni_restart *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_CONNID:
+ out->connid.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNID, (union uni_ieall *)&out->connid, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_RESTART:
+ out->restart.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_RESTART, (union uni_ieall *)&out->restart, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_restart = {
+ 0,
+ "restart",
+ (uni_msg_print_f)print_restart,
+ (uni_msg_check_f)check_restart,
+ (uni_msg_encode_f)encode_restart,
+ (uni_msg_decode_f)decode_restart
+};
+
+static void
+print_restart_ack(struct uni_restart_ack *msg, struct unicx *cx)
+{
+ if(msg->connid.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNID, (union uni_ieall *)&msg->connid, cx);
+ if(msg->restart.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_RESTART, (union uni_ieall *)&msg->restart, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_restart_ack(struct uni_restart_ack *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_CONNID, (union uni_ieall *)&m->connid, cx);
+ ret |= uni_check_ie(UNI_IE_RESTART, (union uni_ieall *)&m->restart, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_restart_ack(struct uni_msg *msg, struct uni_restart_ack *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_RESTART_ACK, cx, &mlen))
+ return (-2);
+
+ if((p->connid.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNID, msg, (union uni_ieall *)&p->connid, cx))
+ return (UNI_IE_CONNID);
+ if((p->restart.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_RESTART, msg, (union uni_ieall *)&p->restart, cx))
+ return (UNI_IE_RESTART);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_restart_ack(struct uni_restart_ack *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_CONNID:
+ out->connid.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNID, (union uni_ieall *)&out->connid, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_RESTART:
+ out->restart.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_RESTART, (union uni_ieall *)&out->restart, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_restart_ack = {
+ 0,
+ "restart_ack",
+ (uni_msg_print_f)print_restart_ack,
+ (uni_msg_check_f)check_restart_ack,
+ (uni_msg_encode_f)encode_restart_ack,
+ (uni_msg_decode_f)decode_restart_ack
+};
+
+static void
+print_add_party(struct uni_add_party *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->aal.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_AAL, (union uni_ieall *)&msg->aal, cx);
+ if(msg->bhli.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_BHLI, (union uni_ieall *)&msg->bhli, cx);
+ if(msg->blli.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_BLLI, (union uni_ieall *)&msg->blli, cx);
+ if(msg->called.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&msg->called, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB; i++)
+ if(msg->calledsub[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLEDSUB, (union uni_ieall *)&msg->calledsub[i], cx);
+ if(msg->calling.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLING, (union uni_ieall *)&msg->calling, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB; i++)
+ if(msg->callingsub[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLINGSUB, (union uni_ieall *)&msg->callingsub[i], cx);
+ if(msg->scompl.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_SCOMPL, (union uni_ieall *)&msg->scompl, cx);
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if(msg->tns[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_TNS, (union uni_ieall *)&msg->tns[i], cx);
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->eetd.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EETD, (union uni_ieall *)&msg->eetd, cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->lij_seqno.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&msg->lij_seqno, cx);
+ if(msg->calling_soft.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLING_SOFT, (union uni_ieall *)&msg->calling_soft, cx);
+ if(msg->called_soft.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED_SOFT, (union uni_ieall *)&msg->called_soft, cx);
+ if(msg->dtl_repeat.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_REPEAT, (union uni_ieall *)&msg->dtl_repeat, cx);
+ for(i = 0; i < UNI_NUM_IE_DTL; i++)
+ if(msg->dtl[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_DTL, (union uni_ieall *)&msg->dtl[i], cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_add_party(struct uni_add_party *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_AAL, (union uni_ieall *)&m->aal, cx);
+ ret |= uni_check_ie(UNI_IE_BHLI, (union uni_ieall *)&m->bhli, cx);
+ ret |= uni_check_ie(UNI_IE_BLLI, (union uni_ieall *)&m->blli, cx);
+ ret |= uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&m->called, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB ; i++) {
+ ret |= uni_check_ie(UNI_IE_CALLEDSUB, (union uni_ieall *)&m->calledsub[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_CALLING, (union uni_ieall *)&m->calling, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB ; i++) {
+ ret |= uni_check_ie(UNI_IE_CALLINGSUB, (union uni_ieall *)&m->callingsub[i], cx);
+ }
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->scompl);
+ else
+ ret |= uni_check_ie(UNI_IE_SCOMPL, (union uni_ieall *)&m->scompl, cx);
+ for(i = 0; i < UNI_NUM_IE_TNS ; i++) {
+ ret |= uni_check_ie(UNI_IE_TNS, (union uni_ieall *)&m->tns[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ ret |= uni_check_ie(UNI_IE_EETD, (union uni_ieall *)&m->eetd, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->lij_seqno);
+ else
+ ret |= uni_check_ie(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&m->lij_seqno, cx);
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->calling_soft);
+ else
+ ret |= uni_check_ie(UNI_IE_CALLING_SOFT, (union uni_ieall *)&m->calling_soft, cx);
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->called_soft);
+ else
+ ret |= uni_check_ie(UNI_IE_CALLED_SOFT, (union uni_ieall *)&m->called_soft, cx);
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->dtl_repeat);
+ else
+ ret |= uni_check_ie(UNI_IE_REPEAT, (union uni_ieall *)&m->dtl_repeat, cx);
+ for(i = 0; i < UNI_NUM_IE_DTL ; i++) {
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->dtl[i]);
+ else
+ ret |= uni_check_ie(UNI_IE_DTL, (union uni_ieall *)&m->dtl[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_add_party(struct uni_msg *msg, struct uni_add_party *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_ADD_PARTY, cx, &mlen))
+ return (-2);
+
+ if((p->aal.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_AAL, msg, (union uni_ieall *)&p->aal, cx))
+ return (UNI_IE_AAL);
+ if((p->bhli.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_BHLI, msg, (union uni_ieall *)&p->bhli, cx))
+ return (UNI_IE_BHLI);
+ if((p->blli.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_BLLI, msg, (union uni_ieall *)&p->blli, cx))
+ return (UNI_IE_BLLI);
+ if((p->called.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED, msg, (union uni_ieall *)&p->called, cx))
+ return (UNI_IE_CALLED);
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB; i++)
+ if((p->calledsub[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLEDSUB, msg, (union uni_ieall *)&p->calledsub[i], cx))
+ return ((i << 16) + UNI_IE_CALLEDSUB);
+ if((p->calling.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLING, msg, (union uni_ieall *)&p->calling, cx))
+ return (UNI_IE_CALLING);
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB; i++)
+ if((p->callingsub[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLINGSUB, msg, (union uni_ieall *)&p->callingsub[i], cx))
+ return ((i << 16) + UNI_IE_CALLINGSUB);
+ if((p->scompl.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_SCOMPL, msg, (union uni_ieall *)&p->scompl, cx))
+ return (UNI_IE_SCOMPL);
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if((p->tns[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_TNS, msg, (union uni_ieall *)&p->tns[i], cx))
+ return ((i << 16) + UNI_IE_TNS);
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->eetd.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EETD, msg, (union uni_ieall *)&p->eetd, cx))
+ return (UNI_IE_EETD);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->lij_seqno.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_LIJ_SEQNO, msg, (union uni_ieall *)&p->lij_seqno, cx))
+ return (UNI_IE_LIJ_SEQNO);
+ if((p->calling_soft.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLING_SOFT, msg, (union uni_ieall *)&p->calling_soft, cx))
+ return (UNI_IE_CALLING_SOFT);
+ if((p->called_soft.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED_SOFT, msg, (union uni_ieall *)&p->called_soft, cx))
+ return (UNI_IE_CALLED_SOFT);
+ if((p->dtl_repeat.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_DTL, msg, (union uni_ieall *)&p->dtl_repeat, cx))
+ return (0x10000000 + UNI_IE_DTL);
+ for(i = 0; i < UNI_NUM_IE_DTL; i++)
+ if((p->dtl[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_DTL, msg, (union uni_ieall *)&p->dtl[i], cx))
+ return ((i << 16) + UNI_IE_DTL);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_add_party(struct uni_add_party *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_AAL:
+ out->aal.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_AAL, (union uni_ieall *)&out->aal, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_BHLI:
+ out->bhli.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_BHLI, (union uni_ieall *)&out->bhli, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_BLLI:
+ out->blli.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_BLLI, (union uni_ieall *)&out->blli, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLED:
+ out->called.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED, (union uni_ieall *)&out->called, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLEDSUB:
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB; i++)
+ if (!IE_ISPRESENT(out->calledsub[i])) {
+ out->calledsub[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLEDSUB, (union uni_ieall *)&out->calledsub[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_CALLING:
+ out->calling.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLING, (union uni_ieall *)&out->calling, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLINGSUB:
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB; i++)
+ if (!IE_ISPRESENT(out->callingsub[i])) {
+ out->callingsub[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLINGSUB, (union uni_ieall *)&out->callingsub[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_SCOMPL:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->scompl.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_SCOMPL, (union uni_ieall *)&out->scompl, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_TNS:
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if (!IE_ISPRESENT(out->tns[i])) {
+ out->tns[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_TNS, (union uni_ieall *)&out->tns[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EETD:
+ out->eetd.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EETD, (union uni_ieall *)&out->eetd, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_LIJ_SEQNO:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->lij_seqno.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&out->lij_seqno, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLING_SOFT:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ out->calling_soft.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLING_SOFT, (union uni_ieall *)&out->calling_soft, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLED_SOFT:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ out->called_soft.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED_SOFT, (union uni_ieall *)&out->called_soft, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_DTL:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ if (IE_ISPRESENT(cx->repeat))
+ out->dtl_repeat = cx->repeat;
+ for(i = 0; i < UNI_NUM_IE_DTL; i++)
+ if (!IE_ISPRESENT(out->dtl[i])) {
+ out->dtl[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_DTL, (union uni_ieall *)&out->dtl[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_REPEAT:
+ cx->repeat.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if (uni_decode_ie_body(UNI_IE_REPEAT, (union uni_ieall *)&cx->repeat, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_add_party = {
+ 0,
+ "add_party",
+ (uni_msg_print_f)print_add_party,
+ (uni_msg_check_f)check_add_party,
+ (uni_msg_encode_f)encode_add_party,
+ (uni_msg_decode_f)decode_add_party
+};
+
+static void
+print_add_party_ack(struct uni_add_party_ack *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->aal.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_AAL, (union uni_ieall *)&msg->aal, cx);
+ if(msg->blli.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_BLLI, (union uni_ieall *)&msg->blli, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->eetd.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EETD, (union uni_ieall *)&msg->eetd, cx);
+ if(msg->conned.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNED, (union uni_ieall *)&msg->conned, cx);
+ if(msg->connedsub.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CONNEDSUB, (union uni_ieall *)&msg->connedsub, cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->called_soft.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED_SOFT, (union uni_ieall *)&msg->called_soft, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_add_party_ack(struct uni_add_party_ack *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_AAL, (union uni_ieall *)&m->aal, cx);
+ ret |= uni_check_ie(UNI_IE_BLLI, (union uni_ieall *)&m->blli, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ ret |= uni_check_ie(UNI_IE_EETD, (union uni_ieall *)&m->eetd, cx);
+ ret |= uni_check_ie(UNI_IE_CONNED, (union uni_ieall *)&m->conned, cx);
+ ret |= uni_check_ie(UNI_IE_CONNEDSUB, (union uni_ieall *)&m->connedsub, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->called_soft);
+ else
+ ret |= uni_check_ie(UNI_IE_CALLED_SOFT, (union uni_ieall *)&m->called_soft, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_add_party_ack(struct uni_msg *msg, struct uni_add_party_ack *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_ADD_PARTY_ACK, cx, &mlen))
+ return (-2);
+
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->aal.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_AAL, msg, (union uni_ieall *)&p->aal, cx))
+ return (UNI_IE_AAL);
+ if((p->blli.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_BLLI, msg, (union uni_ieall *)&p->blli, cx))
+ return (UNI_IE_BLLI);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->eetd.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EETD, msg, (union uni_ieall *)&p->eetd, cx))
+ return (UNI_IE_EETD);
+ if((p->conned.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNED, msg, (union uni_ieall *)&p->conned, cx))
+ return (UNI_IE_CONNED);
+ if((p->connedsub.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CONNEDSUB, msg, (union uni_ieall *)&p->connedsub, cx))
+ return (UNI_IE_CONNEDSUB);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->called_soft.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED_SOFT, msg, (union uni_ieall *)&p->called_soft, cx))
+ return (UNI_IE_CALLED_SOFT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_add_party_ack(struct uni_add_party_ack *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_AAL:
+ out->aal.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_AAL, (union uni_ieall *)&out->aal, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_BLLI:
+ out->blli.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_BLLI, (union uni_ieall *)&out->blli, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EETD:
+ out->eetd.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EETD, (union uni_ieall *)&out->eetd, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CONNED:
+ out->conned.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNED, (union uni_ieall *)&out->conned, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CONNEDSUB:
+ out->connedsub.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CONNEDSUB, (union uni_ieall *)&out->connedsub, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_CALLED_SOFT:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ out->called_soft.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED_SOFT, (union uni_ieall *)&out->called_soft, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_add_party_ack = {
+ 0,
+ "add_party_ack",
+ (uni_msg_print_f)print_add_party_ack,
+ (uni_msg_check_f)check_add_party_ack,
+ (uni_msg_encode_f)encode_add_party_ack,
+ (uni_msg_decode_f)decode_add_party_ack
+};
+
+static void
+print_party_alerting(struct uni_party_alerting *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_party_alerting(struct uni_party_alerting *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_party_alerting(struct uni_msg *msg, struct uni_party_alerting *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_PARTY_ALERTING, cx, &mlen))
+ return (-2);
+
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_party_alerting(struct uni_party_alerting *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_party_alerting = {
+ 0,
+ "party_alerting",
+ (uni_msg_print_f)print_party_alerting,
+ (uni_msg_check_f)check_party_alerting,
+ (uni_msg_encode_f)encode_party_alerting,
+ (uni_msg_decode_f)decode_party_alerting
+};
+
+static void
+print_add_party_rej(struct uni_add_party_rej *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->cause.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CAUSE, (union uni_ieall *)&msg->cause, cx);
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->crankback.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CRANKBACK, (union uni_ieall *)&msg->crankback, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_add_party_rej(struct uni_add_party_rej *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_CAUSE, (union uni_ieall *)&m->cause, cx);
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ if(!(cx->pnni))
+ ret |= IE_ISPRESENT(m->crankback);
+ else
+ ret |= uni_check_ie(UNI_IE_CRANKBACK, (union uni_ieall *)&m->crankback, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_add_party_rej(struct uni_msg *msg, struct uni_add_party_rej *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_ADD_PARTY_REJ, cx, &mlen))
+ return (-2);
+
+ if((p->cause.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CAUSE, msg, (union uni_ieall *)&p->cause, cx))
+ return (UNI_IE_CAUSE);
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->crankback.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CRANKBACK, msg, (union uni_ieall *)&p->crankback, cx))
+ return (UNI_IE_CRANKBACK);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_add_party_rej(struct uni_add_party_rej *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_CAUSE:
+ out->cause.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CAUSE, (union uni_ieall *)&out->cause, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_CRANKBACK:
+ if (!(cx->pnni))
+ return (DEC_ILL);
+ out->crankback.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CRANKBACK, (union uni_ieall *)&out->crankback, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_add_party_rej = {
+ 0,
+ "add_party_rej",
+ (uni_msg_print_f)print_add_party_rej,
+ (uni_msg_check_f)check_add_party_rej,
+ (uni_msg_encode_f)encode_add_party_rej,
+ (uni_msg_decode_f)decode_add_party_rej
+};
+
+static void
+print_drop_party(struct uni_drop_party *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->cause.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CAUSE, (union uni_ieall *)&msg->cause, cx);
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_drop_party(struct uni_drop_party *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_CAUSE, (union uni_ieall *)&m->cause, cx);
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_drop_party(struct uni_msg *msg, struct uni_drop_party *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_DROP_PARTY, cx, &mlen))
+ return (-2);
+
+ if((p->cause.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CAUSE, msg, (union uni_ieall *)&p->cause, cx))
+ return (UNI_IE_CAUSE);
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_drop_party(struct uni_drop_party *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_CAUSE:
+ out->cause.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CAUSE, (union uni_ieall *)&out->cause, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_drop_party = {
+ 0,
+ "drop_party",
+ (uni_msg_print_f)print_drop_party,
+ (uni_msg_check_f)check_drop_party,
+ (uni_msg_encode_f)encode_drop_party,
+ (uni_msg_decode_f)decode_drop_party
+};
+
+static void
+print_drop_party_ack(struct uni_drop_party_ack *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->cause.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CAUSE, (union uni_ieall *)&msg->cause, cx);
+ if(msg->uu.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UU, (union uni_ieall *)&msg->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_drop_party_ack(struct uni_drop_party_ack *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_CAUSE, (union uni_ieall *)&m->cause, cx);
+ if(!(!cx->pnni))
+ ret |= IE_ISPRESENT(m->uu);
+ else
+ ret |= uni_check_ie(UNI_IE_UU, (union uni_ieall *)&m->uu, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_drop_party_ack(struct uni_msg *msg, struct uni_drop_party_ack *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_DROP_PARTY_ACK, cx, &mlen))
+ return (-2);
+
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->cause.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CAUSE, msg, (union uni_ieall *)&p->cause, cx))
+ return (UNI_IE_CAUSE);
+ if((p->uu.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UU, msg, (union uni_ieall *)&p->uu, cx))
+ return (UNI_IE_UU);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_drop_party_ack(struct uni_drop_party_ack *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CAUSE:
+ out->cause.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CAUSE, (union uni_ieall *)&out->cause, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UU:
+ if (!(!cx->pnni))
+ return (DEC_ILL);
+ out->uu.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UU, (union uni_ieall *)&out->uu, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_drop_party_ack = {
+ 0,
+ "drop_party_ack",
+ (uni_msg_print_f)print_drop_party_ack,
+ (uni_msg_check_f)check_drop_party_ack,
+ (uni_msg_encode_f)encode_drop_party_ack,
+ (uni_msg_decode_f)decode_drop_party_ack
+};
+
+static void
+print_leaf_setup_req(struct uni_leaf_setup_req *msg, struct unicx *cx)
+{
+ u_int i;
+
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if(msg->tns[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_TNS, (union uni_ieall *)&msg->tns[i], cx);
+ if(msg->calling.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLING, (union uni_ieall *)&msg->calling, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB; i++)
+ if(msg->callingsub[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLINGSUB, (union uni_ieall *)&msg->callingsub[i], cx);
+ if(msg->called.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&msg->called, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB; i++)
+ if(msg->calledsub[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLEDSUB, (union uni_ieall *)&msg->calledsub[i], cx);
+ if(msg->lij_callid.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_LIJ_CALLID, (union uni_ieall *)&msg->lij_callid, cx);
+ if(msg->lij_seqno.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&msg->lij_seqno, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_leaf_setup_req(struct uni_leaf_setup_req *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ for(i = 0; i < UNI_NUM_IE_TNS ; i++) {
+ ret |= uni_check_ie(UNI_IE_TNS, (union uni_ieall *)&m->tns[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_CALLING, (union uni_ieall *)&m->calling, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB ; i++) {
+ ret |= uni_check_ie(UNI_IE_CALLINGSUB, (union uni_ieall *)&m->callingsub[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&m->called, cx);
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB ; i++) {
+ ret |= uni_check_ie(UNI_IE_CALLEDSUB, (union uni_ieall *)&m->calledsub[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_LIJ_CALLID, (union uni_ieall *)&m->lij_callid, cx);
+ ret |= uni_check_ie(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&m->lij_seqno, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_leaf_setup_req(struct uni_msg *msg, struct uni_leaf_setup_req *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_LEAF_SETUP_REQ, cx, &mlen))
+ return (-2);
+
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if((p->tns[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_TNS, msg, (union uni_ieall *)&p->tns[i], cx))
+ return ((i << 16) + UNI_IE_TNS);
+ if((p->calling.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLING, msg, (union uni_ieall *)&p->calling, cx))
+ return (UNI_IE_CALLING);
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB; i++)
+ if((p->callingsub[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLINGSUB, msg, (union uni_ieall *)&p->callingsub[i], cx))
+ return ((i << 16) + UNI_IE_CALLINGSUB);
+ if((p->called.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED, msg, (union uni_ieall *)&p->called, cx))
+ return (UNI_IE_CALLED);
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB; i++)
+ if((p->calledsub[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLEDSUB, msg, (union uni_ieall *)&p->calledsub[i], cx))
+ return ((i << 16) + UNI_IE_CALLEDSUB);
+ if((p->lij_callid.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_LIJ_CALLID, msg, (union uni_ieall *)&p->lij_callid, cx))
+ return (UNI_IE_LIJ_CALLID);
+ if((p->lij_seqno.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_LIJ_SEQNO, msg, (union uni_ieall *)&p->lij_seqno, cx))
+ return (UNI_IE_LIJ_SEQNO);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_leaf_setup_req(struct uni_leaf_setup_req *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_TNS:
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if (!IE_ISPRESENT(out->tns[i])) {
+ out->tns[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_TNS, (union uni_ieall *)&out->tns[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_CALLING:
+ out->calling.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLING, (union uni_ieall *)&out->calling, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLINGSUB:
+ for(i = 0; i < UNI_NUM_IE_CALLINGSUB; i++)
+ if (!IE_ISPRESENT(out->callingsub[i])) {
+ out->callingsub[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLINGSUB, (union uni_ieall *)&out->callingsub[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_CALLED:
+ out->called.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED, (union uni_ieall *)&out->called, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLEDSUB:
+ for(i = 0; i < UNI_NUM_IE_CALLEDSUB; i++)
+ if (!IE_ISPRESENT(out->calledsub[i])) {
+ out->calledsub[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLEDSUB, (union uni_ieall *)&out->calledsub[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_LIJ_CALLID:
+ out->lij_callid.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_LIJ_CALLID, (union uni_ieall *)&out->lij_callid, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_LIJ_SEQNO:
+ out->lij_seqno.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&out->lij_seqno, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_leaf_setup_req = {
+ 0,
+ "leaf_setup_req",
+ (uni_msg_print_f)print_leaf_setup_req,
+ (uni_msg_check_f)check_leaf_setup_req,
+ (uni_msg_encode_f)encode_leaf_setup_req,
+ (uni_msg_decode_f)decode_leaf_setup_req
+};
+
+static void
+print_leaf_setup_fail(struct uni_leaf_setup_fail *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->cause.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CAUSE, (union uni_ieall *)&msg->cause, cx);
+ if(msg->called.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&msg->called, cx);
+ if(msg->calledsub.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLEDSUB, (union uni_ieall *)&msg->calledsub, cx);
+ if(msg->lij_seqno.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&msg->lij_seqno, cx);
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if(msg->tns[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_TNS, (union uni_ieall *)&msg->tns[i], cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_leaf_setup_fail(struct uni_leaf_setup_fail *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_CAUSE, (union uni_ieall *)&m->cause, cx);
+ ret |= uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&m->called, cx);
+ ret |= uni_check_ie(UNI_IE_CALLEDSUB, (union uni_ieall *)&m->calledsub, cx);
+ ret |= uni_check_ie(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&m->lij_seqno, cx);
+ for(i = 0; i < UNI_NUM_IE_TNS ; i++) {
+ ret |= uni_check_ie(UNI_IE_TNS, (union uni_ieall *)&m->tns[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_leaf_setup_fail(struct uni_msg *msg, struct uni_leaf_setup_fail *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_LEAF_SETUP_FAIL, cx, &mlen))
+ return (-2);
+
+ if((p->cause.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CAUSE, msg, (union uni_ieall *)&p->cause, cx))
+ return (UNI_IE_CAUSE);
+ if((p->called.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED, msg, (union uni_ieall *)&p->called, cx))
+ return (UNI_IE_CALLED);
+ if((p->calledsub.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLEDSUB, msg, (union uni_ieall *)&p->calledsub, cx))
+ return (UNI_IE_CALLEDSUB);
+ if((p->lij_seqno.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_LIJ_SEQNO, msg, (union uni_ieall *)&p->lij_seqno, cx))
+ return (UNI_IE_LIJ_SEQNO);
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if((p->tns[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_TNS, msg, (union uni_ieall *)&p->tns[i], cx))
+ return ((i << 16) + UNI_IE_TNS);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_leaf_setup_fail(struct uni_leaf_setup_fail *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_CAUSE:
+ out->cause.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CAUSE, (union uni_ieall *)&out->cause, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLED:
+ out->called.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED, (union uni_ieall *)&out->called, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLEDSUB:
+ out->calledsub.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLEDSUB, (union uni_ieall *)&out->calledsub, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_LIJ_SEQNO:
+ out->lij_seqno.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_LIJ_SEQNO, (union uni_ieall *)&out->lij_seqno, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_TNS:
+ for(i = 0; i < UNI_NUM_IE_TNS; i++)
+ if (!IE_ISPRESENT(out->tns[i])) {
+ out->tns[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_TNS, (union uni_ieall *)&out->tns[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_leaf_setup_fail = {
+ 0,
+ "leaf_setup_fail",
+ (uni_msg_print_f)print_leaf_setup_fail,
+ (uni_msg_check_f)check_leaf_setup_fail,
+ (uni_msg_encode_f)encode_leaf_setup_fail,
+ (uni_msg_decode_f)decode_leaf_setup_fail
+};
+
+static void
+print_cobisetup(struct uni_cobisetup *msg, struct unicx *cx)
+{
+ if(msg->facility.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_FACILITY, (union uni_ieall *)&msg->facility, cx);
+ if(msg->called.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&msg->called, cx);
+ if(msg->calledsub.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLEDSUB, (union uni_ieall *)&msg->calledsub, cx);
+ if(msg->calling.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLING, (union uni_ieall *)&msg->calling, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_cobisetup(struct uni_cobisetup *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_FACILITY, (union uni_ieall *)&m->facility, cx);
+ ret |= uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&m->called, cx);
+ ret |= uni_check_ie(UNI_IE_CALLEDSUB, (union uni_ieall *)&m->calledsub, cx);
+ ret |= uni_check_ie(UNI_IE_CALLING, (union uni_ieall *)&m->calling, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_cobisetup(struct uni_msg *msg, struct uni_cobisetup *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_COBISETUP, cx, &mlen))
+ return (-2);
+
+ if((p->facility.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_FACILITY, msg, (union uni_ieall *)&p->facility, cx))
+ return (UNI_IE_FACILITY);
+ if((p->called.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED, msg, (union uni_ieall *)&p->called, cx))
+ return (UNI_IE_CALLED);
+ if((p->calledsub.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLEDSUB, msg, (union uni_ieall *)&p->calledsub, cx))
+ return (UNI_IE_CALLEDSUB);
+ if((p->calling.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLING, msg, (union uni_ieall *)&p->calling, cx))
+ return (UNI_IE_CALLING);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_cobisetup(struct uni_cobisetup *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_FACILITY:
+ out->facility.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_FACILITY, (union uni_ieall *)&out->facility, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLED:
+ out->called.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED, (union uni_ieall *)&out->called, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLEDSUB:
+ out->calledsub.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLEDSUB, (union uni_ieall *)&out->calledsub, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLING:
+ out->calling.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLING, (union uni_ieall *)&out->calling, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_cobisetup = {
+ 0,
+ "cobisetup",
+ (uni_msg_print_f)print_cobisetup,
+ (uni_msg_check_f)check_cobisetup,
+ (uni_msg_encode_f)encode_cobisetup,
+ (uni_msg_decode_f)decode_cobisetup
+};
+
+static void
+print_facility(struct uni_facility *msg, struct unicx *cx)
+{
+ if(msg->facility.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_FACILITY, (union uni_ieall *)&msg->facility, cx);
+ if(msg->called.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&msg->called, cx);
+ if(msg->calledsub.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLEDSUB, (union uni_ieall *)&msg->calledsub, cx);
+ if(msg->calling.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CALLING, (union uni_ieall *)&msg->calling, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_facility(struct uni_facility *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_FACILITY, (union uni_ieall *)&m->facility, cx);
+ ret |= uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&m->called, cx);
+ ret |= uni_check_ie(UNI_IE_CALLEDSUB, (union uni_ieall *)&m->calledsub, cx);
+ ret |= uni_check_ie(UNI_IE_CALLING, (union uni_ieall *)&m->calling, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_facility(struct uni_msg *msg, struct uni_facility *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_FACILITY, cx, &mlen))
+ return (-2);
+
+ if((p->facility.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_FACILITY, msg, (union uni_ieall *)&p->facility, cx))
+ return (UNI_IE_FACILITY);
+ if((p->called.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLED, msg, (union uni_ieall *)&p->called, cx))
+ return (UNI_IE_CALLED);
+ if((p->calledsub.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLEDSUB, msg, (union uni_ieall *)&p->calledsub, cx))
+ return (UNI_IE_CALLEDSUB);
+ if((p->calling.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CALLING, msg, (union uni_ieall *)&p->calling, cx))
+ return (UNI_IE_CALLING);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_facility(struct uni_facility *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_FACILITY:
+ out->facility.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_FACILITY, (union uni_ieall *)&out->facility, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLED:
+ out->called.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLED, (union uni_ieall *)&out->called, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLEDSUB:
+ out->calledsub.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLEDSUB, (union uni_ieall *)&out->calledsub, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_CALLING:
+ out->calling.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CALLING, (union uni_ieall *)&out->calling, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_facility = {
+ 0,
+ "facility",
+ (uni_msg_print_f)print_facility,
+ (uni_msg_check_f)check_facility,
+ (uni_msg_encode_f)encode_facility,
+ (uni_msg_decode_f)decode_facility
+};
+
+static void
+print_modify_req(struct uni_modify_req *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->traffic.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_TRAFFIC, (union uni_ieall *)&msg->traffic, cx);
+ if(msg->atraffic.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_ATRAFFIC, (union uni_ieall *)&msg->atraffic, cx);
+ if(msg->mintraffic.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_MINTRAFFIC, (union uni_ieall *)&msg->mintraffic, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_modify_req(struct uni_modify_req *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_TRAFFIC, (union uni_ieall *)&m->traffic, cx);
+ ret |= uni_check_ie(UNI_IE_ATRAFFIC, (union uni_ieall *)&m->atraffic, cx);
+ ret |= uni_check_ie(UNI_IE_MINTRAFFIC, (union uni_ieall *)&m->mintraffic, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_modify_req(struct uni_msg *msg, struct uni_modify_req *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_MODIFY_REQ, cx, &mlen))
+ return (-2);
+
+ if((p->traffic.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_TRAFFIC, msg, (union uni_ieall *)&p->traffic, cx))
+ return (UNI_IE_TRAFFIC);
+ if((p->atraffic.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_ATRAFFIC, msg, (union uni_ieall *)&p->atraffic, cx))
+ return (UNI_IE_ATRAFFIC);
+ if((p->mintraffic.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_MINTRAFFIC, msg, (union uni_ieall *)&p->mintraffic, cx))
+ return (UNI_IE_MINTRAFFIC);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_modify_req(struct uni_modify_req *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_TRAFFIC:
+ out->traffic.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_TRAFFIC, (union uni_ieall *)&out->traffic, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_ATRAFFIC:
+ out->atraffic.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_ATRAFFIC, (union uni_ieall *)&out->atraffic, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_MINTRAFFIC:
+ out->mintraffic.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_MINTRAFFIC, (union uni_ieall *)&out->mintraffic, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_modify_req = {
+ 0,
+ "modify_req",
+ (uni_msg_print_f)print_modify_req,
+ (uni_msg_check_f)check_modify_req,
+ (uni_msg_encode_f)encode_modify_req,
+ (uni_msg_decode_f)decode_modify_req
+};
+
+static void
+print_modify_ack(struct uni_modify_ack *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->report.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_REPORT, (union uni_ieall *)&msg->report, cx);
+ if(msg->traffic.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_TRAFFIC, (union uni_ieall *)&msg->traffic, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_modify_ack(struct uni_modify_ack *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_REPORT, (union uni_ieall *)&m->report, cx);
+ ret |= uni_check_ie(UNI_IE_TRAFFIC, (union uni_ieall *)&m->traffic, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_modify_ack(struct uni_msg *msg, struct uni_modify_ack *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_MODIFY_ACK, cx, &mlen))
+ return (-2);
+
+ if((p->report.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_REPORT, msg, (union uni_ieall *)&p->report, cx))
+ return (UNI_IE_REPORT);
+ if((p->traffic.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_TRAFFIC, msg, (union uni_ieall *)&p->traffic, cx))
+ return (UNI_IE_TRAFFIC);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_modify_ack(struct uni_modify_ack *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_REPORT:
+ out->report.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_REPORT, (union uni_ieall *)&out->report, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_TRAFFIC:
+ out->traffic.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_TRAFFIC, (union uni_ieall *)&out->traffic, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_modify_ack = {
+ 0,
+ "modify_ack",
+ (uni_msg_print_f)print_modify_ack,
+ (uni_msg_check_f)check_modify_ack,
+ (uni_msg_encode_f)encode_modify_ack,
+ (uni_msg_decode_f)decode_modify_ack
+};
+
+static void
+print_modify_rej(struct uni_modify_rej *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->cause.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_CAUSE, (union uni_ieall *)&msg->cause, cx);
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_modify_rej(struct uni_modify_rej *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_CAUSE, (union uni_ieall *)&m->cause, cx);
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_modify_rej(struct uni_msg *msg, struct uni_modify_rej *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_MODIFY_REJ, cx, &mlen))
+ return (-2);
+
+ if((p->cause.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_CAUSE, msg, (union uni_ieall *)&p->cause, cx))
+ return (UNI_IE_CAUSE);
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_modify_rej(struct uni_modify_rej *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_CAUSE:
+ out->cause.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_CAUSE, (union uni_ieall *)&out->cause, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_modify_rej = {
+ 0,
+ "modify_rej",
+ (uni_msg_print_f)print_modify_rej,
+ (uni_msg_check_f)check_modify_rej,
+ (uni_msg_encode_f)encode_modify_rej,
+ (uni_msg_decode_f)decode_modify_rej
+};
+
+static void
+print_conn_avail(struct uni_conn_avail *msg, struct unicx *cx)
+{
+ u_int i;
+
+ if(msg->notify.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_NOTIFY, (union uni_ieall *)&msg->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if(msg->git[i].h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_GIT, (union uni_ieall *)&msg->git[i], cx);
+ if(msg->report.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_REPORT, (union uni_ieall *)&msg->report, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_conn_avail(struct uni_conn_avail *m, struct unicx *cx)
+{
+ int ret = 0;
+ u_int i;
+
+ ret |= uni_check_ie(UNI_IE_NOTIFY, (union uni_ieall *)&m->notify, cx);
+ for(i = 0; i < UNI_NUM_IE_GIT ; i++) {
+ ret |= uni_check_ie(UNI_IE_GIT, (union uni_ieall *)&m->git[i], cx);
+ }
+ ret |= uni_check_ie(UNI_IE_REPORT, (union uni_ieall *)&m->report, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_conn_avail(struct uni_msg *msg, struct uni_conn_avail *p, struct unicx *cx)
+{
+ u_int mlen;
+ u_int i;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_CONN_AVAIL, cx, &mlen))
+ return (-2);
+
+ if((p->notify.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_NOTIFY, msg, (union uni_ieall *)&p->notify, cx))
+ return (UNI_IE_NOTIFY);
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if((p->git[i].h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_GIT, msg, (union uni_ieall *)&p->git[i], cx))
+ return ((i << 16) + UNI_IE_GIT);
+ if((p->report.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_REPORT, msg, (union uni_ieall *)&p->report, cx))
+ return (UNI_IE_REPORT);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_conn_avail(struct uni_conn_avail *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ u_int i;
+
+ switch (ie) {
+
+ case UNI_IE_NOTIFY:
+ out->notify.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_NOTIFY, (union uni_ieall *)&out->notify, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_GIT:
+ for(i = 0; i < UNI_NUM_IE_GIT; i++)
+ if (!IE_ISPRESENT(out->git[i])) {
+ out->git[i].h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_GIT, (union uni_ieall *)&out->git[i], msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+ }
+ break;
+
+ case UNI_IE_REPORT:
+ out->report.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_REPORT, (union uni_ieall *)&out->report, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_conn_avail = {
+ 0,
+ "conn_avail",
+ (uni_msg_print_f)print_conn_avail,
+ (uni_msg_check_f)check_conn_avail,
+ (uni_msg_encode_f)encode_conn_avail,
+ (uni_msg_decode_f)decode_conn_avail
+};
+
+static void
+print_unknown(struct uni_unknown *msg, struct unicx *cx)
+{
+ if(msg->epref.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_EPREF, (union uni_ieall *)&msg->epref, cx);
+ if(msg->unrec.h.present & UNI_IE_PRESENT)
+ uni_print_ie_internal(UNI_IE_UNREC, (union uni_ieall *)&msg->unrec, cx);
+}
+
+static int
+check_unknown(struct uni_unknown *m, struct unicx *cx)
+{
+ int ret = 0;
+
+ ret |= uni_check_ie(UNI_IE_EPREF, (union uni_ieall *)&m->epref, cx);
+ ret |= uni_check_ie(UNI_IE_UNREC, (union uni_ieall *)&m->unrec, cx);
+
+ return ret;
+}
+
+static int
+encode_unknown(struct uni_msg *msg, struct uni_unknown *p, struct unicx *cx)
+{
+ u_int mlen;
+
+ if(uni_encode_msg_hdr(msg, &p->hdr, UNI_UNKNOWN, cx, &mlen))
+ return (-2);
+
+ if((p->epref.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_EPREF, msg, (union uni_ieall *)&p->epref, cx))
+ return (UNI_IE_EPREF);
+ if((p->unrec.h.present & UNI_IE_PRESENT) &&
+ uni_encode_ie(UNI_IE_UNREC, msg, (union uni_ieall *)&p->unrec, cx))
+ return (UNI_IE_UNREC);
+
+ msg->b_buf[mlen+0] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 8;
+ msg->b_buf[mlen+1] = ((msg->b_wptr-msg->b_rptr)-mlen-2) >> 0;
+
+ return (0);
+}
+
+static int
+decode_unknown(struct uni_unknown *out, struct uni_msg *msg,
+ enum uni_ietype ie, struct uni_iehdr *hdr, u_int ielen,
+ struct unicx *cx)
+{
+ switch (ie) {
+
+ case UNI_IE_EPREF:
+ out->epref.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_EPREF, (union uni_ieall *)&out->epref, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ case UNI_IE_UNREC:
+ out->unrec.h = *hdr;
+ if (hdr->present & UNI_IE_ERROR)
+ return (DEC_ERR);
+ if(uni_decode_ie_body(UNI_IE_UNREC, (union uni_ieall *)&out->unrec, msg, ielen, cx))
+ return (DEC_ERR);
+ break;
+
+ default:
+ return (DEC_ILL);
+ }
+ return (DEC_OK);
+}
+
+static const struct msgdecl decl_unknown = {
+ 0,
+ "unknown",
+ (uni_msg_print_f)print_unknown,
+ (uni_msg_check_f)check_unknown,
+ (uni_msg_encode_f)encode_unknown,
+ (uni_msg_decode_f)decode_unknown
+};
+
+const struct msgdecl *uni_msgtable[256] = {
+ &decl_unknown, /* 0x00 */
+ &decl_alerting, /* 0x01 */
+ &decl_call_proc, /* 0x02 */
+ &decl_unknown, /* 0x03 */
+ &decl_unknown, /* 0x04 */
+ &decl_setup, /* 0x05 */
+ &decl_unknown, /* 0x06 */
+ &decl_connect, /* 0x07 */
+ &decl_unknown, /* 0x08 */
+ &decl_unknown, /* 0x09 */
+ &decl_unknown, /* 0x0a */
+ &decl_unknown, /* 0x0b */
+ &decl_unknown, /* 0x0c */
+ &decl_unknown, /* 0x0d */
+ &decl_unknown, /* 0x0e */
+ &decl_connect_ack, /* 0x0f */
+ &decl_unknown, /* 0x10 */
+ &decl_unknown, /* 0x11 */
+ &decl_unknown, /* 0x12 */
+ &decl_unknown, /* 0x13 */
+ &decl_unknown, /* 0x14 */
+ &decl_cobisetup, /* 0x15 */
+ &decl_unknown, /* 0x16 */
+ &decl_unknown, /* 0x17 */
+ &decl_unknown, /* 0x18 */
+ &decl_unknown, /* 0x19 */
+ &decl_unknown, /* 0x1a */
+ &decl_unknown, /* 0x1b */
+ &decl_unknown, /* 0x1c */
+ &decl_unknown, /* 0x1d */
+ &decl_unknown, /* 0x1e */
+ &decl_unknown, /* 0x1f */
+ &decl_unknown, /* 0x20 */
+ &decl_unknown, /* 0x21 */
+ &decl_unknown, /* 0x22 */
+ &decl_unknown, /* 0x23 */
+ &decl_unknown, /* 0x24 */
+ &decl_unknown, /* 0x25 */
+ &decl_unknown, /* 0x26 */
+ &decl_unknown, /* 0x27 */
+ &decl_unknown, /* 0x28 */
+ &decl_unknown, /* 0x29 */
+ &decl_unknown, /* 0x2a */
+ &decl_unknown, /* 0x2b */
+ &decl_unknown, /* 0x2c */
+ &decl_unknown, /* 0x2d */
+ &decl_unknown, /* 0x2e */
+ &decl_unknown, /* 0x2f */
+ &decl_unknown, /* 0x30 */
+ &decl_unknown, /* 0x31 */
+ &decl_unknown, /* 0x32 */
+ &decl_unknown, /* 0x33 */
+ &decl_unknown, /* 0x34 */
+ &decl_unknown, /* 0x35 */
+ &decl_unknown, /* 0x36 */
+ &decl_unknown, /* 0x37 */
+ &decl_unknown, /* 0x38 */
+ &decl_unknown, /* 0x39 */
+ &decl_unknown, /* 0x3a */
+ &decl_unknown, /* 0x3b */
+ &decl_unknown, /* 0x3c */
+ &decl_unknown, /* 0x3d */
+ &decl_unknown, /* 0x3e */
+ &decl_unknown, /* 0x3f */
+ &decl_unknown, /* 0x40 */
+ &decl_unknown, /* 0x41 */
+ &decl_unknown, /* 0x42 */
+ &decl_unknown, /* 0x43 */
+ &decl_unknown, /* 0x44 */
+ &decl_unknown, /* 0x45 */
+ &decl_restart, /* 0x46 */
+ &decl_unknown, /* 0x47 */
+ &decl_unknown, /* 0x48 */
+ &decl_unknown, /* 0x49 */
+ &decl_unknown, /* 0x4a */
+ &decl_unknown, /* 0x4b */
+ &decl_unknown, /* 0x4c */
+ &decl_release, /* 0x4d */
+ &decl_restart_ack, /* 0x4e */
+ &decl_unknown, /* 0x4f */
+ &decl_unknown, /* 0x50 */
+ &decl_unknown, /* 0x51 */
+ &decl_unknown, /* 0x52 */
+ &decl_unknown, /* 0x53 */
+ &decl_unknown, /* 0x54 */
+ &decl_unknown, /* 0x55 */
+ &decl_unknown, /* 0x56 */
+ &decl_unknown, /* 0x57 */
+ &decl_unknown, /* 0x58 */
+ &decl_unknown, /* 0x59 */
+ &decl_release_compl, /* 0x5a */
+ &decl_unknown, /* 0x5b */
+ &decl_unknown, /* 0x5c */
+ &decl_unknown, /* 0x5d */
+ &decl_unknown, /* 0x5e */
+ &decl_unknown, /* 0x5f */
+ &decl_unknown, /* 0x60 */
+ &decl_unknown, /* 0x61 */
+ &decl_facility, /* 0x62 */
+ &decl_unknown, /* 0x63 */
+ &decl_unknown, /* 0x64 */
+ &decl_unknown, /* 0x65 */
+ &decl_unknown, /* 0x66 */
+ &decl_unknown, /* 0x67 */
+ &decl_unknown, /* 0x68 */
+ &decl_unknown, /* 0x69 */
+ &decl_unknown, /* 0x6a */
+ &decl_unknown, /* 0x6b */
+ &decl_unknown, /* 0x6c */
+ &decl_unknown, /* 0x6d */
+ &decl_notify, /* 0x6e */
+ &decl_unknown, /* 0x6f */
+ &decl_unknown, /* 0x70 */
+ &decl_unknown, /* 0x71 */
+ &decl_unknown, /* 0x72 */
+ &decl_unknown, /* 0x73 */
+ &decl_unknown, /* 0x74 */
+ &decl_status_enq, /* 0x75 */
+ &decl_unknown, /* 0x76 */
+ &decl_unknown, /* 0x77 */
+ &decl_unknown, /* 0x78 */
+ &decl_unknown, /* 0x79 */
+ &decl_unknown, /* 0x7a */
+ &decl_unknown, /* 0x7b */
+ &decl_unknown, /* 0x7c */
+ &decl_status, /* 0x7d */
+ &decl_unknown, /* 0x7e */
+ &decl_unknown, /* 0x7f */
+ &decl_add_party, /* 0x80 */
+ &decl_add_party_ack, /* 0x81 */
+ &decl_add_party_rej, /* 0x82 */
+ &decl_drop_party, /* 0x83 */
+ &decl_drop_party_ack, /* 0x84 */
+ &decl_party_alerting, /* 0x85 */
+ &decl_unknown, /* 0x86 */
+ &decl_unknown, /* 0x87 */
+ &decl_modify_req, /* 0x88 */
+ &decl_modify_ack, /* 0x89 */
+ &decl_modify_rej, /* 0x8a */
+ &decl_conn_avail, /* 0x8b */
+ &decl_unknown, /* 0x8c */
+ &decl_unknown, /* 0x8d */
+ &decl_unknown, /* 0x8e */
+ &decl_unknown, /* 0x8f */
+ &decl_leaf_setup_fail, /* 0x90 */
+ &decl_leaf_setup_req, /* 0x91 */
+ &decl_unknown, /* 0x92 */
+ &decl_unknown, /* 0x93 */
+ &decl_unknown, /* 0x94 */
+ &decl_unknown, /* 0x95 */
+ &decl_unknown, /* 0x96 */
+ &decl_unknown, /* 0x97 */
+ &decl_unknown, /* 0x98 */
+ &decl_unknown, /* 0x99 */
+ &decl_unknown, /* 0x9a */
+ &decl_unknown, /* 0x9b */
+ &decl_unknown, /* 0x9c */
+ &decl_unknown, /* 0x9d */
+ &decl_unknown, /* 0x9e */
+ &decl_unknown, /* 0x9f */
+ &decl_unknown, /* 0xa0 */
+ &decl_unknown, /* 0xa1 */
+ &decl_unknown, /* 0xa2 */
+ &decl_unknown, /* 0xa3 */
+ &decl_unknown, /* 0xa4 */
+ &decl_unknown, /* 0xa5 */
+ &decl_unknown, /* 0xa6 */
+ &decl_unknown, /* 0xa7 */
+ &decl_unknown, /* 0xa8 */
+ &decl_unknown, /* 0xa9 */
+ &decl_unknown, /* 0xaa */
+ &decl_unknown, /* 0xab */
+ &decl_unknown, /* 0xac */
+ &decl_unknown, /* 0xad */
+ &decl_unknown, /* 0xae */
+ &decl_unknown, /* 0xaf */
+ &decl_unknown, /* 0xb0 */
+ &decl_unknown, /* 0xb1 */
+ &decl_unknown, /* 0xb2 */
+ &decl_unknown, /* 0xb3 */
+ &decl_unknown, /* 0xb4 */
+ &decl_unknown, /* 0xb5 */
+ &decl_unknown, /* 0xb6 */
+ &decl_unknown, /* 0xb7 */
+ &decl_unknown, /* 0xb8 */
+ &decl_unknown, /* 0xb9 */
+ &decl_unknown, /* 0xba */
+ &decl_unknown, /* 0xbb */
+ &decl_unknown, /* 0xbc */
+ &decl_unknown, /* 0xbd */
+ &decl_unknown, /* 0xbe */
+ &decl_unknown, /* 0xbf */
+ &decl_unknown, /* 0xc0 */
+ &decl_unknown, /* 0xc1 */
+ &decl_unknown, /* 0xc2 */
+ &decl_unknown, /* 0xc3 */
+ &decl_unknown, /* 0xc4 */
+ &decl_unknown, /* 0xc5 */
+ &decl_unknown, /* 0xc6 */
+ &decl_unknown, /* 0xc7 */
+ &decl_unknown, /* 0xc8 */
+ &decl_unknown, /* 0xc9 */
+ &decl_unknown, /* 0xca */
+ &decl_unknown, /* 0xcb */
+ &decl_unknown, /* 0xcc */
+ &decl_unknown, /* 0xcd */
+ &decl_unknown, /* 0xce */
+ &decl_unknown, /* 0xcf */
+ &decl_unknown, /* 0xd0 */
+ &decl_unknown, /* 0xd1 */
+ &decl_unknown, /* 0xd2 */
+ &decl_unknown, /* 0xd3 */
+ &decl_unknown, /* 0xd4 */
+ &decl_unknown, /* 0xd5 */
+ &decl_unknown, /* 0xd6 */
+ &decl_unknown, /* 0xd7 */
+ &decl_unknown, /* 0xd8 */
+ &decl_unknown, /* 0xd9 */
+ &decl_unknown, /* 0xda */
+ &decl_unknown, /* 0xdb */
+ &decl_unknown, /* 0xdc */
+ &decl_unknown, /* 0xdd */
+ &decl_unknown, /* 0xde */
+ &decl_unknown, /* 0xdf */
+ &decl_unknown, /* 0xe0 */
+ &decl_unknown, /* 0xe1 */
+ &decl_unknown, /* 0xe2 */
+ &decl_unknown, /* 0xe3 */
+ &decl_unknown, /* 0xe4 */
+ &decl_unknown, /* 0xe5 */
+ &decl_unknown, /* 0xe6 */
+ &decl_unknown, /* 0xe7 */
+ &decl_unknown, /* 0xe8 */
+ &decl_unknown, /* 0xe9 */
+ &decl_unknown, /* 0xea */
+ &decl_unknown, /* 0xeb */
+ &decl_unknown, /* 0xec */
+ &decl_unknown, /* 0xed */
+ &decl_unknown, /* 0xee */
+ &decl_unknown, /* 0xef */
+ &decl_unknown, /* 0xf0 */
+ &decl_unknown, /* 0xf1 */
+ &decl_unknown, /* 0xf2 */
+ &decl_unknown, /* 0xf3 */
+ &decl_unknown, /* 0xf4 */
+ &decl_unknown, /* 0xf5 */
+ &decl_unknown, /* 0xf6 */
+ &decl_unknown, /* 0xf7 */
+ &decl_unknown, /* 0xf8 */
+ &decl_unknown, /* 0xf9 */
+ &decl_unknown, /* 0xfa */
+ &decl_unknown, /* 0xfb */
+ &decl_unknown, /* 0xfc */
+ &decl_unknown, /* 0xfd */
+ &decl_unknown, /* 0xfe */
+ &decl_unknown, /* 0xff */
+};
diff --git a/sys/contrib/ngatm/netnatm/msg/uni_msg.h b/sys/contrib/ngatm/netnatm/msg/uni_msg.h
new file mode 100644
index 000000000000..ddb095b612c5
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uni_msg.h
@@ -0,0 +1,342 @@
+/* This file was created automatically
+ * Source file: $Begemot: libunimsg/atm/msg/msg.def,v 1.3 2003/09/19 11:58:15 hbb Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _NETNATM_MSG_UNI_MSG_H_
+#define _NETNATM_MSG_UNI_MSG_H_
+
+struct uni_alerting {
+ struct uni_msghdr hdr;
+ struct uni_ie_connid connid;
+ struct uni_ie_epref epref;
+ struct uni_ie_notify notify;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_uu uu;
+ struct uni_ie_report report;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_call_proc {
+ struct uni_msghdr hdr;
+ struct uni_ie_connid connid;
+ struct uni_ie_epref epref;
+ struct uni_ie_notify notify;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_connect {
+ struct uni_msghdr hdr;
+ struct uni_ie_aal aal;
+ struct uni_ie_blli blli;
+ struct uni_ie_connid connid;
+ struct uni_ie_epref epref;
+ struct uni_ie_notify notify;
+ struct uni_ie_conned conned;
+ struct uni_ie_connedsub connedsub;
+ struct uni_ie_eetd eetd;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_uu uu;
+ struct uni_ie_traffic traffic;
+ struct uni_ie_exqos exqos;
+ struct uni_ie_facility facility;
+ struct uni_ie_abrsetup abrsetup;
+ struct uni_ie_abradd abradd;
+ struct uni_ie_called_soft called_soft;
+ struct uni_ie_report report;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_connect_ack {
+ struct uni_msghdr hdr;
+ struct uni_ie_notify notify;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_release {
+ struct uni_msghdr hdr;
+ struct uni_ie_cause cause[2];
+ struct uni_ie_notify notify;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_uu uu;
+ struct uni_ie_facility facility;
+ struct uni_ie_crankback crankback;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_release_compl {
+ struct uni_msghdr hdr;
+ struct uni_ie_cause cause[2];
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_uu uu;
+ struct uni_ie_crankback crankback;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_setup {
+ struct uni_msghdr hdr;
+ struct uni_ie_aal aal;
+ struct uni_ie_traffic traffic;
+ struct uni_ie_bearer bearer;
+ struct uni_ie_bhli bhli;
+ struct uni_ie_repeat blli_repeat;
+ struct uni_ie_blli blli[UNI_NUM_IE_BLLI];
+ struct uni_ie_called called;
+ struct uni_ie_calledsub calledsub[UNI_NUM_IE_CALLEDSUB];
+ struct uni_ie_calling calling;
+ struct uni_ie_callingsub callingsub[UNI_NUM_IE_CALLINGSUB];
+ struct uni_ie_connid connid;
+ struct uni_ie_qos qos;
+ struct uni_ie_eetd eetd;
+ struct uni_ie_notify notify;
+ struct uni_ie_scompl scompl;
+ struct uni_ie_tns tns[UNI_NUM_IE_TNS];
+ struct uni_ie_epref epref;
+ struct uni_ie_atraffic atraffic;
+ struct uni_ie_mintraffic mintraffic;
+ struct uni_ie_uu uu;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_lij_callid lij_callid;
+ struct uni_ie_lij_param lij_param;
+ struct uni_ie_lij_seqno lij_seqno;
+ struct uni_ie_exqos exqos;
+ struct uni_ie_abrsetup abrsetup;
+ struct uni_ie_abradd abradd;
+ struct uni_ie_cscope cscope;
+ struct uni_ie_calling_soft calling_soft;
+ struct uni_ie_called_soft called_soft;
+ struct uni_ie_repeat dtl_repeat;
+ struct uni_ie_dtl dtl[UNI_NUM_IE_DTL];
+ struct uni_ie_report report;
+ struct uni_ie_mdcr mdcr;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_status {
+ struct uni_msghdr hdr;
+ struct uni_ie_callstate callstate;
+ struct uni_ie_cause cause;
+ struct uni_ie_epref epref;
+ struct uni_ie_epstate epstate;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_status_enq {
+ struct uni_msghdr hdr;
+ struct uni_ie_epref epref;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_notify {
+ struct uni_msghdr hdr;
+ struct uni_ie_notify notify;
+ struct uni_ie_epref epref;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_restart {
+ struct uni_msghdr hdr;
+ struct uni_ie_connid connid;
+ struct uni_ie_restart restart;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_restart_ack {
+ struct uni_msghdr hdr;
+ struct uni_ie_connid connid;
+ struct uni_ie_restart restart;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_add_party {
+ struct uni_msghdr hdr;
+ struct uni_ie_aal aal;
+ struct uni_ie_bhli bhli;
+ struct uni_ie_blli blli;
+ struct uni_ie_called called;
+ struct uni_ie_calledsub calledsub[UNI_NUM_IE_CALLEDSUB];
+ struct uni_ie_calling calling;
+ struct uni_ie_callingsub callingsub[UNI_NUM_IE_CALLINGSUB];
+ struct uni_ie_scompl scompl;
+ struct uni_ie_tns tns[UNI_NUM_IE_TNS];
+ struct uni_ie_epref epref;
+ struct uni_ie_notify notify;
+ struct uni_ie_eetd eetd;
+ struct uni_ie_uu uu;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_lij_seqno lij_seqno;
+ struct uni_ie_calling_soft calling_soft;
+ struct uni_ie_called_soft called_soft;
+ struct uni_ie_repeat dtl_repeat;
+ struct uni_ie_dtl dtl[UNI_NUM_IE_DTL];
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_add_party_ack {
+ struct uni_msghdr hdr;
+ struct uni_ie_epref epref;
+ struct uni_ie_aal aal;
+ struct uni_ie_blli blli;
+ struct uni_ie_notify notify;
+ struct uni_ie_eetd eetd;
+ struct uni_ie_conned conned;
+ struct uni_ie_connedsub connedsub;
+ struct uni_ie_uu uu;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_called_soft called_soft;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_party_alerting {
+ struct uni_msghdr hdr;
+ struct uni_ie_epref epref;
+ struct uni_ie_notify notify;
+ struct uni_ie_uu uu;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_add_party_rej {
+ struct uni_msghdr hdr;
+ struct uni_ie_cause cause;
+ struct uni_ie_epref epref;
+ struct uni_ie_uu uu;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_crankback crankback;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_drop_party {
+ struct uni_msghdr hdr;
+ struct uni_ie_cause cause;
+ struct uni_ie_epref epref;
+ struct uni_ie_notify notify;
+ struct uni_ie_uu uu;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_drop_party_ack {
+ struct uni_msghdr hdr;
+ struct uni_ie_epref epref;
+ struct uni_ie_cause cause;
+ struct uni_ie_uu uu;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_leaf_setup_req {
+ struct uni_msghdr hdr;
+ struct uni_ie_tns tns[UNI_NUM_IE_TNS];
+ struct uni_ie_calling calling;
+ struct uni_ie_callingsub callingsub[UNI_NUM_IE_CALLINGSUB];
+ struct uni_ie_called called;
+ struct uni_ie_calledsub calledsub[UNI_NUM_IE_CALLEDSUB];
+ struct uni_ie_lij_callid lij_callid;
+ struct uni_ie_lij_seqno lij_seqno;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_leaf_setup_fail {
+ struct uni_msghdr hdr;
+ struct uni_ie_cause cause;
+ struct uni_ie_called called;
+ struct uni_ie_calledsub calledsub;
+ struct uni_ie_lij_seqno lij_seqno;
+ struct uni_ie_tns tns[UNI_NUM_IE_TNS];
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_cobisetup {
+ struct uni_msghdr hdr;
+ struct uni_ie_facility facility;
+ struct uni_ie_called called;
+ struct uni_ie_calledsub calledsub;
+ struct uni_ie_calling calling;
+ struct uni_ie_notify notify;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_facility {
+ struct uni_msghdr hdr;
+ struct uni_ie_facility facility;
+ struct uni_ie_called called;
+ struct uni_ie_calledsub calledsub;
+ struct uni_ie_calling calling;
+ struct uni_ie_notify notify;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_modify_req {
+ struct uni_msghdr hdr;
+ struct uni_ie_traffic traffic;
+ struct uni_ie_atraffic atraffic;
+ struct uni_ie_mintraffic mintraffic;
+ struct uni_ie_notify notify;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_modify_ack {
+ struct uni_msghdr hdr;
+ struct uni_ie_report report;
+ struct uni_ie_traffic traffic;
+ struct uni_ie_notify notify;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_modify_rej {
+ struct uni_msghdr hdr;
+ struct uni_ie_cause cause;
+ struct uni_ie_notify notify;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_conn_avail {
+ struct uni_msghdr hdr;
+ struct uni_ie_notify notify;
+ struct uni_ie_git git[UNI_NUM_IE_GIT];
+ struct uni_ie_report report;
+ struct uni_ie_unrec unrec;
+};
+
+struct uni_unknown {
+ struct uni_msghdr hdr;
+ struct uni_ie_epref epref;
+ struct uni_ie_unrec unrec;
+};
+
+union uni_msgall {
+ struct uni_msghdr hdr;
+ struct uni_alerting alerting;
+ struct uni_call_proc call_proc;
+ struct uni_connect connect;
+ struct uni_connect_ack connect_ack; /* !pnni */
+ struct uni_release release;
+ struct uni_release_compl release_compl;
+ struct uni_setup setup;
+ struct uni_status status;
+ struct uni_status_enq status_enq;
+ struct uni_notify notify;
+ struct uni_restart restart;
+ struct uni_restart_ack restart_ack;
+ struct uni_add_party add_party;
+ struct uni_add_party_ack add_party_ack;
+ struct uni_party_alerting party_alerting;
+ struct uni_add_party_rej add_party_rej;
+ struct uni_drop_party drop_party;
+ struct uni_drop_party_ack drop_party_ack;
+ struct uni_leaf_setup_req leaf_setup_req; /* !pnni */
+ struct uni_leaf_setup_fail leaf_setup_fail; /* !pnni */
+ struct uni_cobisetup cobisetup; /* !pnni&&q2932 */
+ struct uni_facility facility; /* !pnni&&q2932 */
+ struct uni_modify_req modify_req; /* !pnni */
+ struct uni_modify_ack modify_ack; /* !pnni */
+ struct uni_modify_rej modify_rej; /* !pnni */
+ struct uni_conn_avail conn_avail; /* !pnni */
+ struct uni_unknown unknown;
+};
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/msg/unimsglib.h b/sys/contrib/ngatm/netnatm/msg/unimsglib.h
new file mode 100644
index 000000000000..f8489dbffc0c
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/unimsglib.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $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_
+
+#include <netnatm/msg/uni_config.h>
+
+struct uni_msg;
+
+enum uni_ierr_type {
+ UNI_IERR_UNK, /* unknown IE */
+ UNI_IERR_LEN, /* length error */
+ UNI_IERR_BAD, /* content error */
+ UNI_IERR_ACC, /* access element content error */
+ UNI_IERR_MIS, /* mandatory IE missing (not used here) */
+};
+
+struct uni_ierr {
+ enum uni_ierr_type err; /* what error */
+ enum uni_ieact act; /* the action indicator */
+ u_int ie:8; /* the ie type */
+ u_int man:1; /* mandatory flag */
+ u_int epref:1;/* Q.2971 9.5.3.2.1 low-pri epref */
+};
+
+/*
+ * Context buffer. Needed to reduce number of arguments to routines.
+ */
+struct unicx {
+ /*
+ * globals for error handling
+ */
+ u_int errcnt; /* number of bad IEs */
+ struct uni_ierr err[UNI_MAX_ERRIE]; /* the errors */
+
+ int q2932; /* Enable GFP */
+ int pnni; /* Enable PNNI */
+
+ int git_hard; /* do hard check on GIT IE */
+ int bearer_hard; /* do hard check on BEARER IE */
+ int cause_hard; /* do hard check on cause */
+
+ int multiline; /* printing mode */
+ u_int tabsiz; /* tabulation size */
+
+ /*
+ * Internal context of library -- don't touch
+ */
+ struct uni_ie_repeat repeat; /* repeat IE during decoding */
+ enum uni_ietype ielast; /* last IE seen for repeat handling */
+
+ const char *prefix[20];
+ u_int nprefix;
+ int doindent;
+ char *buf;
+ size_t bufsiz;
+ u_int indent; /* indentation */
+ int dont_init;
+};
+
+/*
+ * Functions for all messages
+ */
+void uni_print_cref(char *, size_t, const struct uni_cref *, struct unicx *);
+void uni_print_msghdr(char *, size_t, const struct uni_msghdr *, struct unicx *);
+void uni_print(char *, size_t, const struct uni_all *, struct unicx *);
+void uni_print_msg(char *, size_t, u_int _mtype, const union uni_msgall *,
+ struct unicx *);
+int uni_encode(struct uni_msg *, struct uni_all *, struct unicx *);
+int uni_decode(struct uni_msg *, struct uni_all *, struct unicx *);
+
+int uni_decode_head(struct uni_msg *, struct uni_all *, struct unicx *);
+int uni_decode_body(struct uni_msg *, struct uni_all *, struct unicx *);
+
+int uni_encode_msg_hdr(struct uni_msg *, struct uni_msghdr *, enum uni_msgtype,
+ struct unicx *, int *);
+
+
+/*
+ * Functions for all information elements
+ */
+void uni_print_ie(char *, size_t, enum uni_ietype, const union uni_ieall *,
+ struct unicx *);
+int uni_check_ie(enum uni_ietype, union uni_ieall *, struct unicx *);
+int uni_encode_ie(enum uni_ietype, struct uni_msg *, union uni_ieall *,
+ struct unicx *);
+int uni_decode_ie_hdr(enum uni_ietype *, struct uni_iehdr *, struct uni_msg *,
+ struct unicx *, u_int *);
+int uni_encode_ie_hdr(struct uni_msg *, enum uni_ietype, struct uni_iehdr *,
+ u_int, struct unicx *);
+int uni_decode_ie_body(enum uni_ietype, union uni_ieall *, struct uni_msg *,
+ u_int, struct unicx *);
+
+
+/*
+ * Context handling
+ */
+void uni_initcx(struct unicx *);
+void uni_print_cx(char *, size_t, struct unicx *);
+
+#define UNI_SAVE_IERR(CX, IETYPE, ACT, ERRCODE) \
+ (((CX)->errcnt < UNI_MAX_ERRIE) ? \
+ ((CX)->err[(CX)->errcnt].ie = (IETYPE), \
+ (CX)->err[(CX)->errcnt].act = (ACT), \
+ (CX)->err[(CX)->errcnt].err = (ERRCODE), \
+ (CX)->err[(CX)->errcnt].man = 0, \
+ (CX)->errcnt++, \
+ 1) : 0)
+
+/*
+ * Traffic classification
+ */
+enum uni_traffic_class {
+ UNI_TRAFFIC_CBR1,
+ UNI_TRAFFIC_CBR2,
+ UNI_TRAFFIC_CBR3,
+ UNI_TRAFFIC_rtVBR1,
+ UNI_TRAFFIC_rtVBR2,
+ UNI_TRAFFIC_rtVBR3,
+ UNI_TRAFFIC_rtVBR4,
+ UNI_TRAFFIC_rtVBR5,
+ UNI_TRAFFIC_rtVBR6,
+ UNI_TRAFFIC_nrtVBR1,
+ UNI_TRAFFIC_nrtVBR2,
+ UNI_TRAFFIC_nrtVBR3,
+ UNI_TRAFFIC_nrtVBR4,
+ UNI_TRAFFIC_nrtVBR5,
+ UNI_TRAFFIC_nrtVBR6,
+ UNI_TRAFFIC_ABR,
+ UNI_TRAFFIC_UBR1,
+ UNI_TRAFFIC_UBR2,
+};
+
+/* classify traffic */
+int uni_classify_traffic(const struct uni_ie_bearer *,
+ const struct uni_ie_traffic *,
+ enum uni_traffic_class *, enum uni_traffic_class *,
+ char *, size_t);
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/msg/uniprint.h b/sys/contrib/ngatm/netnatm/msg/uniprint.h
new file mode 100644
index 000000000000..239fa2dd4076
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uniprint.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $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.
+ */
+#ifndef _NETNATM_MSG_UNIPRINT_H_
+#define _NETNATM_MSG_UNIPRINT_H_
+
+#include <netnatm/msg/uni_config.h>
+
+/*
+ * This structure is used to define value->string mappings.
+ * It must be terminated by a { NULL, 0 } entry.
+ */
+struct uni_print_tbl {
+ const char *name;
+ u_int val;
+};
+void uni_print_tbl(const char *_entry, u_int _val,
+ const struct uni_print_tbl *_tbl, struct unicx *_cx);
+
+/* initialize printing. This must be called at the start from each external
+ * callable printing function. */
+void uni_print_init(char *_buf, size_t _bufsiz, struct unicx *_cx);
+
+/* End the current (semantical) line. This takes care of indendation and
+ * actually print the newline in the appropriate modes. */
+void uni_print_eol(struct unicx *_cx);
+
+/* Push or pop a prefix. This takes care of indendation. */
+void uni_print_push_prefix(const char *_prefix, struct unicx *_cx);
+void uni_print_pop_prefix(struct unicx *_cx);
+
+/* Print a flag taking care of the right prefixing */
+void uni_print_flag(const char *_flag, struct unicx *_cx);
+
+/* Print an entry taking care of the right prefixing */
+void uni_print_entry(struct unicx *_cx, const char *_entry,
+ const char *_fmt, ...) __printflike(3, 4);
+
+/* Generic printf */
+void uni_printf(struct unicx *_cx, const char *_fmt, ...) __printflike(2, 3);
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/msg/unistruct.h b/sys/contrib/ngatm/netnatm/msg/unistruct.h
new file mode 100644
index 000000000000..ceb1f5b5f8d4
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/unistruct.h
@@ -0,0 +1,1371 @@
+/*
+ * Copyright (c) 1996-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/msg/unistruct.h,v 1.7 2004/07/16 18:42:22 brandt Exp $
+ *
+ * This file defines all structures that are used by
+ * API users.
+ */
+#ifndef _NETNATM_MSG_UNISTRUCT_H_
+#define _NETNATM_MSG_UNISTRUCT_H_
+
+#include <netnatm/msg/uni_config.h>
+
+/*
+ * define IE and MSG header
+ */
+#include <netnatm/msg/uni_hdr.h>
+
+/*
+ * define all IE's
+ */
+/*************************************************************************
+ *
+ * Free FORM IE
+ */
+struct uni_ie_unrec {
+ struct uni_iehdr h;
+ uint8_t id; /* ID of this IE */
+ u_int len; /* data length */
+ u_char data[128]; /* arbitrary maximum length */
+};
+
+/*************************************************************************
+ *
+ * ATM adaptation layer parameters information element
+ */
+enum {
+ UNI_AAL_SUB_ID = 0x85,
+ UNI_AAL_CBR_ID = 0x86,
+ UNI_AAL_MULT_ID = 0x87,
+ UNI_AAL_SCREC_ID = 0x88,
+ UNI_AAL_ECM_ID = 0x89,
+ UNI_AAL_BSIZE_ID = 0x8a,
+ UNI_AAL_PART_ID = 0x8b,
+ UNI_AAL_FWDCPCS_ID = 0x8c,
+ UNI_AAL_BWDCPCS_ID = 0x81,
+ UNI_AAL_MID_ID = 0x82,
+ UNI_AAL_SSCS_ID = 0x84,
+};
+
+enum uni_aal {
+ UNI_AAL_0 = 0x00, /* voice */
+ UNI_AAL_1 = 0x01,
+ UNI_AAL_2 = 0x02,
+ UNI_AAL_4 = 0x03, /* same as AAL 3 */
+ UNI_AAL_5 = 0x05,
+ UNI_AAL_USER = 0x10,
+};
+enum uni_aal1_subtype {
+ UNI_AAL1_SUB_NULL = 0x00,
+ UNI_AAL1_SUB_VOICE = 0x01,
+ UNI_AAL1_SUB_CIRCUIT = 0x02,
+ UNI_AAL1_SUB_HQAUDIO = 0x04,
+ UNI_AAL1_SUB_VIDEO = 0x05,
+};
+enum uni_aal1_cbr {
+ UNI_AAL1_CBR_64 = 0x01,
+ UNI_AAL1_CBR_1544 = 0x04,
+ UNI_AAL1_CBR_6312 = 0x05,
+ UNI_AAL1_CBR_32064 = 0x06,
+ UNI_AAL1_CBR_44736 = 0x07,
+ UNI_AAL1_CBR_97728 = 0x08,
+ UNI_AAL1_CBR_2048 = 0x10,
+ UNI_AAL1_CBR_8448 = 0x11,
+ UNI_AAL1_CBR_34368 = 0x12,
+ UNI_AAL1_CBR_139264 = 0x13,
+ UNI_AAL1_CBR_N64 = 0x40,
+ UNI_AAL1_CBR_N8 = 0x41,
+};
+enum uni_aal1_screc {
+ UNI_AAL1_SCREC_NULL = 0x00, /* synchr. circuit transport */
+ UNI_AAL1_SCREC_SRTS = 0x01, /* synchr. residual timestamp */
+ UNI_AAL1_SCREC_ACLK = 0x02, /* adaptive clock */
+};
+enum uni_aal1_ecm {
+ UNI_AAL1_ECM_NULL = 0x00, /* no error correction */
+ UNI_AAL1_ECM_LOSS = 0x01, /* for loss sensitive signals */
+ UNI_AAL1_ECM_DELAY = 0x02, /* for delay sensitive signals */
+};
+enum uni_aal_sscs {
+ UNI_AAL_SSCS_NULL = 0x00, /* Null */
+ UNI_AAL_SSCS_SSCOPA = 0x01, /* assured SSCOP */
+ UNI_AAL_SSCS_SSCOPU = 0x02, /* unassured SSCOP */
+ UNI_AAL_SSCS_FRAME = 0x04, /* frame relay */
+};
+
+struct uni_ie_aal {
+ struct uni_iehdr h;
+ enum uni_aal type; /* aal type */
+
+ union {
+#define UNI_AAL1_MULT_P 0x01
+#define UNI_AAL1_SCREC_P 0x02
+#define UNI_AAL1_ECM_P 0x04
+#define UNI_AAL1_BSIZE_P 0x08
+#define UNI_AAL1_PART_P 0x10
+ struct {
+ enum uni_aal1_subtype subtype; /* AAL1 subtype */
+ enum uni_aal1_cbr cbr_rate; /* AAL1 CBR rate */
+ u_int mult; /* AAL1 CBR mutliplier */
+ enum uni_aal1_screc screc; /* AAL1 source clock recovery */
+ enum uni_aal1_ecm ecm; /* AAL1 error correction */
+ u_int bsize; /* AAL1 SDT blocksize */
+ u_int part; /* AAL1 partial cell fill */
+ } aal1;
+
+#define UNI_AAL4_CPCS_P 0x01
+#define UNI_AAL4_MID_P 0x02
+#define UNI_AAL4_SSCS_P 0x04
+ struct {
+ u_int fwd_cpcs; /* max fwd cpcs blocksize */
+ u_int bwd_cpcs; /* max bkw cpcs blocksize */
+ u_int mid_low; /* MID low range */
+ u_int mid_high; /* MID high range */
+ enum uni_aal_sscs sscs; /* sscs type */
+ } aal4;
+
+#define UNI_AAL5_CPCS_P 0x01
+#define UNI_AAL5_SSCS_P 0x02
+ struct {
+ u_int fwd_cpcs; /* max fwd cpcs blocksize */
+ u_int bwd_cpcs; /* max bkw cpcs blocksize */
+ enum uni_aal_sscs sscs; /* sscs type */
+ } aal5;
+
+ struct {
+ u_int len; /* number of bytes */
+ u_char user[4]; /* user data */
+ } aalu;
+ } u;
+};
+
+/*************************************************************************
+ *
+ * Called party number information element
+ * Called party subaddress information element
+ * Calling party number information element
+ * Calling party subaddress information element
+ * Q.2951/UNI4.0 Connected number information element
+ * Q.2951/UNI4.0 Connected subaddress information element
+ */
+enum uni_addr_type {
+ UNI_ADDR_UNKNOWN = 0x0,
+ UNI_ADDR_INTERNATIONAL = 0x1,
+ UNI_ADDR_NATIONAL = 0x2, /* not sup */
+ UNI_ADDR_NETWORK = 0x3, /* not sup */
+ UNI_ADDR_SUBSCR = 0x4, /* not sup */
+ UNI_ADDR_ABBR = 0x6, /* not sup */
+};
+enum uni_addr_plan {
+ /* UNI_ADDR_UNKNOWN = 0x0, */ /* not sup */
+ UNI_ADDR_E164 = 0x1,
+ UNI_ADDR_ATME = 0x2,
+ UNI_ADDR_DATA = 0x3, /* not sup */
+ UNI_ADDR_PRIVATE = 0x9, /* not sup */
+};
+enum uni_subaddr_type {
+ UNI_SUBADDR_NSAP = 0x0,
+ UNI_SUBADDR_ATME = 0x1,
+ UNI_SUBADDR_USER = 0x2, /* not sup */
+};
+enum uni_addr_pres {
+ UNI_ADDR_PRES = 0x0,
+ UNI_ADDR_RESTRICT = 0x1,
+ UNI_ADDR_NONUMBER = 0x2,
+};
+enum uni_addr_screen {
+ UNI_ADDR_SCREEN_NOT = 0x0,
+ UNI_ADDR_SCREEN_PASSED = 0x1,
+ UNI_ADDR_SCREEN_FAILED = 0x2,
+ UNI_ADDR_SCREEN_NET = 0x3,
+};
+
+/* don't use bitfields to get a defined structure layout */
+struct uni_addr {
+ uint8_t type;
+ uint8_t plan;
+ uint8_t len;
+ u_char addr[UNI_ADDR_MAXLEN];
+};
+struct uni_subaddr {
+ enum uni_subaddr_type type;
+ u_int len;
+ u_char addr[UNI_SUBADDR_MAXLEN];
+};
+
+struct uni_ie_called {
+ struct uni_iehdr h;
+ struct uni_addr addr;
+};
+
+struct uni_ie_calledsub {
+ struct uni_iehdr h;
+ struct uni_subaddr addr;
+};
+
+struct uni_ie_calling {
+ struct uni_iehdr h;
+#define UNI_CALLING_SCREEN_P 0x0001
+
+ struct uni_addr addr;
+ enum uni_addr_pres pres;
+ enum uni_addr_screen screen;
+};
+
+struct uni_ie_callingsub {
+ struct uni_iehdr h;
+ struct uni_subaddr addr;
+};
+
+struct uni_ie_conned {
+ struct uni_iehdr h;
+#define UNI_CONNED_SCREEN_P 0x0001
+
+ struct uni_addr addr;
+ enum uni_addr_pres pres;
+ enum uni_addr_screen screen;
+};
+
+struct uni_ie_connedsub {
+ struct uni_iehdr h;
+ struct uni_subaddr addr;
+};
+
+/*************************************************************************
+ *
+ * Broadband bearer capability descriptor
+ * On reception of an old bearer descriptor, it is automatically
+ * converted to a new, legal one.
+ */
+enum uni_bearer_class {
+ UNI_BEARER_A = 0x01,
+ UNI_BEARER_C = 0x03,
+ UNI_BEARER_X = 0x10,
+ UNI_BEARER_TVP = 0x30,
+};
+
+enum uni_bearer_atc {
+ UNI_BEARER_ATC_CBR = 0x05,
+ UNI_BEARER_ATC_CBR1 = 0x07,
+ UNI_BEARER_ATC_VBR = 0x09,
+ UNI_BEARER_ATC_VBR1 = 0x13,
+ UNI_BEARER_ATC_NVBR = 0x0a,
+ UNI_BEARER_ATC_NVBR1 = 0x0b,
+ UNI_BEARER_ATC_ABR = 0x0c,
+
+ UNI_BEARER_ATCX_0 = 0x00,
+ UNI_BEARER_ATCX_1 = 0x01,
+ UNI_BEARER_ATCX_2 = 0x02,
+ UNI_BEARER_ATCX_4 = 0x04,
+ UNI_BEARER_ATCX_6 = 0x06,
+ UNI_BEARER_ATCX_8 = 0x08,
+};
+
+enum uni_bearer_clip {
+ UNI_BEARER_NOCLIP = 0x0,
+ UNI_BEARER_CLIP = 0x1,
+};
+
+enum uni_bearer_cfg {
+ UNI_BEARER_P2P = 0x0,
+ UNI_BEARER_MP = 0x1,
+};
+
+struct uni_ie_bearer {
+ struct uni_iehdr h;
+#define UNI_BEARER_ATC_P 0x02
+
+ enum uni_bearer_class bclass; /* bearer class */
+ enum uni_bearer_atc atc; /* ATM transfer capability */
+ enum uni_bearer_clip clip; /* suspectibility to clipping */
+ enum uni_bearer_cfg cfg; /* u-plane configuration */
+};
+
+/*************************************************************************
+ *
+ * Broadband higher layer information element
+ */
+enum uni_bhli {
+ UNI_BHLI_ISO = 0x00, /* IDO defined */
+ UNI_BHLI_USER = 0x01, /* user specific */
+ UNI_BHLI_VENDOR = 0x03, /* vendor specific */
+};
+
+struct uni_ie_bhli {
+ struct uni_iehdr h;
+ enum uni_bhli type;
+ u_char info[8];
+ u_int len;
+};
+
+/*************************************************************************
+ *
+ * Boradband lower layer information element
+ */
+enum {
+ UNI_BLLI_L1_ID = 0x1,
+ UNI_BLLI_L2_ID = 0x2,
+ UNI_BLLI_L3_ID = 0x3,
+};
+
+enum uni_blli_l2 {
+ UNI_BLLI_L2_BASIC = 0x01,
+ UNI_BLLI_L2_Q921 = 0x02,
+ UNI_BLLI_L2_X25LL = 0x06,
+ UNI_BLLI_L2_X25ML = 0x07,
+ UNI_BLLI_L2_LABP = 0x08,
+ UNI_BLLI_L2_HDLC_ARM = 0x09,
+ UNI_BLLI_L2_HDLC_NRM = 0x0a,
+ UNI_BLLI_L2_HDLC_ABM = 0x0b,
+ UNI_BLLI_L2_LAN = 0x0c,
+ UNI_BLLI_L2_X75 = 0x0d,
+ UNI_BLLI_L2_Q922 = 0x0e,
+ UNI_BLLI_L2_USER = 0x10,
+ UNI_BLLI_L2_ISO7776 = 0x11,
+};
+
+enum uni_blli_l2_mode {
+ UNI_BLLI_L2NORM = 0x1,
+ UNI_BLLI_L2EXT = 0x2,
+};
+
+enum uni_blli_l3 {
+ UNI_BLLI_L3_X25 = 0x06,
+ UNI_BLLI_L3_ISO8208 = 0x07,
+ UNI_BLLI_L3_X223 = 0x08,
+ UNI_BLLI_L3_CLMP = 0x09,
+ UNI_BLLI_L3_T70 = 0x0a,
+ UNI_BLLI_L3_TR9577 = 0x0b,
+ UNI_BLLI_L3_H310 = 0x0c,
+ UNI_BLLI_L3_H321 = 0x0d,
+ UNI_BLLI_L3_USER = 0x10,
+};
+
+enum uni_blli_l3_mode {
+ UNI_BLLI_L3NSEQ = 0x1, /* normal sequence numbering */
+ UNI_BLLI_L3ESEQ = 0x2, /* extended sequence numbering */
+};
+
+enum uni_blli_l3_psiz {
+ UNI_BLLI_L3_16 = 0x4, /* 16 byte packets */
+ UNI_BLLI_L3_32 = 0x5, /* 32 byte packets */
+ UNI_BLLI_L3_64 = 0x6, /* 64 byte packets */
+ UNI_BLLI_L3_128 = 0x7, /* 128 byte packets */
+ UNI_BLLI_L3_256 = 0x8, /* 256 byte packets */
+ UNI_BLLI_L3_512 = 0x9, /* 512 byte packets */
+ UNI_BLLI_L3_1024 = 0xa, /* 1024 byte packets */
+ UNI_BLLI_L3_2048 = 0xb, /* 2048 byte packets */
+ UNI_BLLI_L3_4096 = 0xc, /* 4096 byte packets */
+};
+
+enum uni_blli_l3_ttype {
+ UNI_BLLI_L3_TTYPE_RECV = 0x1, /* receive only */
+ UNI_BLLI_L3_TTYPE_SEND = 0x2, /* send only */
+ UNI_BLLI_L3_TTYPE_BOTH = 0x3, /* both */
+};
+
+enum uni_blli_l3_mux {
+ UNI_BLLI_L3_MUX_NOMUX = 0, /* no multiplexing */
+ UNI_BLLI_L3_MUX_TS = 1, /* transport stream */
+ UNI_BLLI_L3_MUX_TSFEC = 2, /* transport stream with FEC */
+ UNI_BLLI_L3_MUX_PS = 3, /* program stream */
+ UNI_BLLI_L3_MUX_PSFEC = 4, /* program stream with FEC */
+ UNI_BLLI_L3_MUX_H221 = 5, /* H.221 */
+};
+
+enum uni_blli_l3_tcap {
+ UNI_BLLI_L3_TCAP_NOIND = 0, /* no indication */
+ UNI_BLLI_L3_TCAP_AAL1 = 1, /* only AAL1 */
+ UNI_BLLI_L3_TCAP_AAL5 = 2, /* only AAL5 */
+ UNI_BLLI_L3_TCAP_AAL15 = 3, /* AAL1 and AAL5 */
+};
+
+/* Value for l3_ipi: */
+enum {
+ UNI_BLLI_L3_SNAP = 0x80, /* IEEE 802.1 SNAP */
+};
+
+struct uni_ie_blli {
+ struct uni_iehdr h;
+#define UNI_BLLI_L1_P 0x0001
+#define UNI_BLLI_L2_P 0x0002
+#define UNI_BLLI_L2_Q933_P 0x0004
+#define UNI_BLLI_L2_WSIZ_P 0x0008
+#define UNI_BLLI_L2_USER_P 0x0010
+#define UNI_BLLI_L3_P 0x0020
+#define UNI_BLLI_L3_MODE_P 0x0040
+#define UNI_BLLI_L3_PSIZ_P 0x0080
+#define UNI_BLLI_L3_WSIZ_P 0x0100
+#define UNI_BLLI_L3_USER_P 0x0200
+#define UNI_BLLI_L3_IPI_P 0x0400
+#define UNI_BLLI_L3_SNAP_P 0x0800
+#define UNI_BLLI_L3_TTYPE_P 0x1000
+#define UNI_BLLI_L3_MUX_P 0x2000
+
+ u_int l1:5; /* layer 1 info */
+
+ enum uni_blli_l2 l2; /* layer 2 info */
+ u_int l2_q933:2; /* layer 2 Q.933 use */
+ enum uni_blli_l2_mode l2_mode; /* layer 2 HDLC mode */
+ u_char l2_user; /* layer 2 user info */
+ u_char l2_wsiz; /* layer 2 window size */
+
+ enum uni_blli_l3 l3; /* layer 3 info */
+ enum uni_blli_l3_mode l3_mode; /* layer 3 mode */
+ enum uni_blli_l3_psiz l3_psiz; /* layer 3 default packet size */
+ u_char l3_wsiz; /* layer 3 window size */
+ u_char l3_user; /* layer 3 user info */
+ u_char l3_ipi; /* IPI byte */
+ u_int oui; /* OUI bytes */
+ u_int pid; /* PID bytes */
+ enum uni_blli_l3_ttype l3_ttype; /* terminal bytes */
+ enum uni_blli_l3_tcap l3_tcap; /* terminal capability */
+ enum uni_blli_l3_mux l3_fmux; /* forward muxing */
+ enum uni_blli_l3_mux l3_bmux; /* forward muxing */
+};
+
+/*************************************************************************
+ *
+ * Transit network selection IE
+ */
+struct uni_ie_tns {
+ struct uni_iehdr h;
+ u_char net[UNI_TNS_MAXLEN];
+ u_int len;
+};
+
+/*************************************************************************
+ *
+ * Call state information element
+ */
+enum uni_callstate {
+ UNI_CALLSTATE_U0 = 0x00,
+ UNI_CALLSTATE_N0 = 0x00,
+ UNI_CALLSTATE_NN0 = 0x00,
+
+ UNI_CALLSTATE_U1 = 0x01,
+ UNI_CALLSTATE_N1 = 0x01,
+ UNI_CALLSTATE_NN1 = 0x01,
+
+ UNI_CALLSTATE_U3 = 0x03,
+ UNI_CALLSTATE_N3 = 0x03,
+ UNI_CALLSTATE_NN3 = 0x03,
+
+ UNI_CALLSTATE_U4 = 0x04,
+ UNI_CALLSTATE_N4 = 0x04,
+ UNI_CALLSTATE_NN4 = 0x04,
+
+ UNI_CALLSTATE_U6 = 0x06,
+ UNI_CALLSTATE_N6 = 0x06,
+ UNI_CALLSTATE_NN6 = 0x06,
+
+ UNI_CALLSTATE_U7 = 0x07,
+ UNI_CALLSTATE_N7 = 0x07,
+ UNI_CALLSTATE_NN7 = 0x07,
+
+ UNI_CALLSTATE_U8 = 0x08,
+ UNI_CALLSTATE_N8 = 0x08,
+
+ UNI_CALLSTATE_U9 = 0x09,
+ UNI_CALLSTATE_N9 = 0x09,
+ UNI_CALLSTATE_NN9 = 0x09,
+
+ UNI_CALLSTATE_U10 = 0x0a,
+ UNI_CALLSTATE_N10 = 0x0a,
+ UNI_CALLSTATE_NN10 = 0x0a,
+
+ UNI_CALLSTATE_U11 = 0x0b,
+ UNI_CALLSTATE_N11 = 0x0b,
+ UNI_CALLSTATE_NN11 = 0x0b,
+
+ UNI_CALLSTATE_U12 = 0x0c,
+ UNI_CALLSTATE_N12 = 0x0c,
+ UNI_CALLSTATE_NN12 = 0x0c,
+
+ UNI_CALLSTATE_REST0 = 0x00,
+ UNI_CALLSTATE_REST1 = 0x3d,
+ UNI_CALLSTATE_REST2 = 0x3e,
+
+ UNI_CALLSTATE_U13 = 0x0d,
+ UNI_CALLSTATE_N13 = 0x0d,
+
+ UNI_CALLSTATE_U14 = 0x0e,
+ UNI_CALLSTATE_N14 = 0x0e,
+};
+
+struct uni_ie_callstate {
+ struct uni_iehdr h;
+ enum uni_callstate state;
+};
+
+/*************************************************************************
+ *
+ * Cause information element
+ */
+enum uni_cause_loc {
+ UNI_CAUSE_LOC_USER = 0x0,
+ UNI_CAUSE_LOC_PRIVLOC = 0x1,
+ UNI_CAUSE_LOC_PUBLOC = 0x2,
+ UNI_CAUSE_LOC_TRANSIT = 0x3,
+ UNI_CAUSE_LOC_PUBREM = 0x4,
+ UNI_CAUSE_LOC_PRIVREM = 0x5,
+ UNI_CAUSE_LOC_INTERNAT = 0x6,
+ UNI_CAUSE_LOC_BEYOND = 0x7,
+};
+
+#define UNI_DECLARE_CAUSE_VALUES \
+D(UNALL_NUM, 0x01 /* 1*/, COND, Q.850, "Unallocated (unassigned) number") \
+D(NOROUTE_NET, 0x02 /* 2*/, TNS, Q.850, "No route to specified transit network") \
+D(NOROUTE, 0x03 /* 3*/, COND, Q.850, "No route to destination") \
+D(SPTONE, 0x04 /* 4*/, NONE, Q.850, "Send special information tone") \
+D(BADTRUNK, 0x05 /* 5*/, NONE, Q.850, "Misdialled trunk prefix") \
+D(BADCHAN, 0x06 /* 6*/, NONE, Q.850, "Channel unacceptable") \
+D(CALLAWARDED, 0x07 /* 7*/, NONE, Q.850, "Call awarded and being delivered in an established channel") \
+D(PREEMPT, 0x08 /* 8*/, NONE, Q.850, "Preemption") \
+D(PREEMPT_RES, 0x09 /* 9*/, NONE, Q.850, "Preemption - circuit reserved for reuse") \
+D(CLEARING, 0x10 /* 16*/, COND, Q.850, "Normal call clearing") \
+D(BUSY, 0x11 /* 17*/, CCBS, Q.850, "User busy") \
+D(NO_RESPONSE, 0x12 /* 18*/, NONE, Q.850, "No user responding") \
+D(NO_RESP_ALERT,0x13 /* 19*/, NONE, Q.850, "No answer from user (user alerted)") \
+D(ABSENT, 0x14 /* 20*/, NONE, Q.850, "Subscriber absent") \
+D(REJECTED, 0x15 /* 21*/, REJ, Q.850, "Call rejected") \
+D(NUMCHG, 0x16 /* 22*/, NUMBER, Q.850, "Number changed") \
+D(REDIR, 0x17 /* 23*/, NONE, Q.850, "Redirection to new destination") \
+N(CLIR_REJECTED,0x17 /* 23*/, NONE, UNI4.0, "User rejects call with calling line identification restriction (CLIR)") \
+D(EXCHG_ERR, 0x19 /* 25*/, NONE, Q.850, "Exchange routing error") \
+D(NOSEL_CLEAR, 0x1a /* 26*/, NONE, Q.850, "Non-selected user clearing") \
+D(DST_OOO, 0x1b /* 27*/, NONE, Q.850, "Destination out of order") \
+D(INV_ADDR, 0x1c /* 28*/, NONE, Q.850, "Invalid number format (address incomplete)") \
+D(FAC_REJ, 0x1d /* 29*/, FAC, Q.850, "Facility rejected") \
+D(STATUS, 0x1e /* 30*/, NONE, Q.850, "Response to STATUS ENQUIRY") \
+D(UNSPEC, 0x1f /* 31*/, NONE, Q.850, "Normal, unspecified") \
+D(TMY_PARTY, 0x20 /* 32*/, NONE, Q.2971, "Too many pending add party requests") \
+D(NOCHAN, 0x22 /* 34*/, CCBS, Q.850, "No circuit/channel available") \
+N(SOFT_NAVL, 0x22 /* 34*/, NONE, PNNI1.0,"Requested called party soft PVPC or PVCC not available")\
+D(VPCI_NAVL, 0x23 /* 35*/, NONE, Q.2610, "Requested VPCI/VCI not available") \
+D(VPCI_FAIL, 0x24 /* 36*/, NONE, Q.2610, "VPCI/VPI assignment failure") \
+D(CRATE_NAVL, 0x25 /* 37*/, CRATE, Q.2610, "User cell rate not available") \
+D(NET_OOO, 0x26 /* 38*/, NONE, Q.850, "Network out of order") \
+D(FRAME_OOS, 0x27 /* 39*/, NONE, Q.850, "Permanent frame mode connection out of service") \
+D(FRAME_OP, 0x28 /* 40*/, NONE, Q.850, "Permanent frame mode connection operational") \
+D(TEMP, 0x29 /* 41*/, NONE, Q.850, "Temporary failure") \
+D(CONG, 0x2a /* 42*/, NONE, Q.850, "Switching equipment congestion") \
+D(ACC_DISC, 0x2b /* 43*/, IE, Q.850, "Access information discarded") \
+D(REQNOCHAN, 0x2c /* 44*/, NONE, Q.850, "Requested circuit/channel not available") \
+D(NOVPCI, 0x2d /* 45*/, NONE, Q.2610, "No VPCI/VCI available") \
+D(PREC_BLOCK, 0x2e /* 46*/, NONE, Q.850, "Precedence call blocked") \
+D(RESRC_NAVL, 0x2f /* 47*/, NONE, Q.850, "Resource unavailable, unspecified") \
+D(QOS_NAVL, 0x31 /* 49*/, COND, Q.850, "Quality of service not available") \
+D(FAC_NOTSUB, 0x32 /* 50*/, FAC, Q.850, "Requested facility not subscribed") \
+D(OUT_CUG, 0x35 /* 53*/, NONE, Q.850, "Outgoing calls barred within CUG") \
+N(PGL_CHG, 0x35 /* 53*/, NONE, PNNI1.0,"Call cleared due to change in PGL") \
+D(IN_CUG, 0x37 /* 55*/, NONE, Q.850, "Incoming call barred within CUG") \
+D(BEARER_NAUTH, 0x39 /* 57*/, ATTR, Q.850, "Bearer capability not authorized") \
+D(BEARER_NAVL, 0x3a /* 58*/, ATTR, Q.850, "Bearer capability not presently available") \
+D(INCONS, 0x3e /* 62*/, NONE, Q.850, "Inconsistency in designated outgoing access information and subscriber class") \
+D(OPT_NAVL, 0x3f /* 63*/, NONE, Q.850, "Service or option not available, unspecified") \
+D(BEARER_NIMPL, 0x41 /* 65*/, ATTR, Q.850, "Bearer capability not implemented") \
+D(CHANNEL_NIMPL,0x42 /* 66*/, CHANNEL, Q.850, "Channel type not implemented") \
+D(FAC_NIMPL, 0x45 /* 69*/, FAC, Q.850, "Requested facility not implemented") \
+D(RESTR_DIG, 0x46 /* 70*/, NONE, Q.850, "Only restricted digital information bearer capability is available") \
+D(TRAFFIC_UNSUP,0x49 /* 73*/, NONE, Q.2971, "Unsupported combination of traffic parameters") \
+N(AAL_UNSUP, 0x4c /* 78*/, NONE, UNI3.1, "AAL parameters cannot be supported") \
+D(CREF_INV, 0x51 /* 81*/, NONE, Q.850, "Invalid call reference value") \
+D(CHANNEL_NEX, 0x52 /* 82*/, CHANID, Q.850, "Identified channel does not exist") \
+D(SUSPENDED, 0x53 /* 83*/, NONE, Q.850, "A suspended call exists, but this call identity does not") \
+D(CID_INUSE, 0x54 /* 84*/, NONE, Q.850, "Call identity in use") \
+D(NOTSUSP, 0x55 /* 85*/, NONE, Q.850, "No call suspended") \
+D(CLEARED, 0x56 /* 86*/, CAUSE, Q.850, "Call having requested call identity has been cleared") \
+D(NOT_MEMBER, 0x57 /* 87*/, NONE, Q.850, "User not member of CUG") \
+D(INCOMP, 0x58 /* 88*/, PARAM, Q.850, "Incompatible destination") \
+D(ENDP_INV, 0x59 /* 89*/, IE, UNI3.1, "Invalid endpoint reference") \
+D(NEX_CUG, 0x5a /* 90*/, NONE, Q.850, "Non-existend CUG") \
+D(TRANSIT_INV, 0x5b /* 91*/, NONE, Q.850, "Invalid transit network selection") \
+D(AALNOTSUPP, 0x5d /* 93*/, NONE, Q.2610, "AAL parameters cannot be supported") \
+D(INVMSG, 0x5f /* 95*/, NONE, Q.850, "Invalid message, unspecified") \
+D(MANDAT, 0x60 /* 96*/, IE, Q.850, "Mandatory information element is missing") \
+D(MTYPE_NIMPL, 0x61 /* 97*/, MTYPE, Q.850, "Message type non-existent or not implemented") \
+D(MSG_NOTCOMP, 0x62 /* 98*/, MTYPE, Q.850, "Message not compatible with call state or message type non-existent or not implemented") \
+D(IE_NIMPL, 0x63 /* 99*/, IE, Q.850, "Information element/parameter non-existent or not implemented") \
+D(IE_INV, 0x64 /*100*/, IE, Q.850, "Invalid information element contents") \
+D(MSG_INCOMP, 0x65 /*101*/, MTYPE, Q.850, "Message not compatible with call state") \
+D(RECOVER, 0x66 /*102*/, TIMER, Q.850, "Recovery on timer expiry") \
+D(PARAM_NEX, 0x67 /*103*/, PARAM, Q.850, "Parameter non-existent or not implemented, passed on") \
+N(BAD_LENGTH, 0x68 /*104*/, NONE, UNI3.1, "Incorrect message length") \
+D(PARAM_UNREC, 0x6e /*110*/, PARAM, Q.850, "Message with unrecognized parameter, discarded") \
+D(PROTO, 0x6f /*111*/, NONE, Q.850, "Protocol error, unspecified") \
+D(INTERWORKING, 0x7f /*127*/, NONE, Q.850, "Interworking, unspecified")
+
+#define D(NAME,VAL,DIAG,STD,STR) UNI_CAUSE_##NAME = VAL,
+#define N(NAME,VAL,DIAG,STD,STR) UNI_CAUSE_##NAME = VAL,
+
+enum uni_cause {
+UNI_DECLARE_CAUSE_VALUES
+};
+
+#undef D
+#undef N
+
+enum uni_cause_class {
+ UNI_CAUSE_CLASS_NORM = 0x0,
+ UNI_CAUSE_CLASS_NORM1 = 0x1,
+ UNI_CAUSE_CLASS_RES = 0x2,
+ UNI_CAUSE_CLASS_NAVL = 0x3,
+ UNI_CAUSE_CLASS_NIMPL = 0x4,
+ UNI_CAUSE_CLASS_INV = 0x5,
+ UNI_CAUSE_CLASS_PROTO = 0x6,
+ UNI_CAUSE_CLASS_INTER = 0x7,
+};
+enum uni_cause_pu {
+ UNI_CAUSE_PU_PROVIDER = 0,
+ UNI_CAUSE_PU_USER = 1,
+};
+enum uni_cause_na {
+ UNI_CAUSE_NA_NORMAL = 0,
+ UNI_CAUSE_NA_ABNORMAL = 1,
+};
+enum uni_cause_cond {
+ UNI_CAUSE_COND_UNKNOWN = 0,
+ UNI_CAUSE_COND_PERM = 1,
+ UNI_CAUSE_COND_TRANS = 2,
+};
+enum uni_cause_reason {
+ UNI_CAUSE_REASON_USER = 0x00,
+ UNI_CAUSE_REASON_IEMISS = 0x01,
+ UNI_CAUSE_REASON_IESUFF = 0x02,
+};
+
+enum uni_diag {
+ UNI_DIAG_NONE, /* no diagnostics */
+
+ UNI_DIAG_COND, /* Condition */
+ UNI_DIAG_TNS, /* Transit Network Selector */
+ UNI_DIAG_REJ, /* Call Rejected */
+ UNI_DIAG_NUMBER, /* New Destination */
+ UNI_DIAG_CRATE, /* Traffic descriptor subfield */
+ UNI_DIAG_ATTR, /* Attribute idendity */
+ UNI_DIAG_PARAM, /* Parameter, same as one IE */
+ UNI_DIAG_TIMER, /* timer in ASCII */
+ UNI_DIAG_MTYPE, /* Message type */
+ UNI_DIAG_IE, /* Information element */
+ UNI_DIAG_CHANID, /* VPCI/VCI */
+
+ UNI_DIAG_CAUSE = UNI_DIAG_NONE, /* Not specified */
+ UNI_DIAG_CHANNEL = UNI_DIAG_NONE, /* For N-ISDN */
+ UNI_DIAG_CCBS = UNI_DIAG_NONE, /* Not used in Q.931 */
+ UNI_DIAG_FAC = UNI_DIAG_NONE, /* Not specified */
+};
+
+enum {
+ UNI_CAUSE_TRAFFIC_N = 34-6,
+ UNI_CAUSE_IE_N = 34-6,
+ UNI_CAUSE_ATTR_N = (34-6)/3,
+};
+
+struct uni_ie_cause {
+ struct uni_iehdr h;
+#define UNI_CAUSE_COND_P 0x0001
+#define UNI_CAUSE_REJ_P 0x0002
+#define UNI_CAUSE_REJ_USER_P 0x0004
+#define UNI_CAUSE_REJ_IE_P 0x0008
+#define UNI_CAUSE_IE_P 0x0010
+#define UNI_CAUSE_TRAFFIC_P 0x0020
+#define UNI_CAUSE_VPCI_P 0x0040
+#define UNI_CAUSE_MTYPE_P 0x0080
+#define UNI_CAUSE_TIMER_P 0x0100
+#define UNI_CAUSE_TNS_P 0x0200
+#define UNI_CAUSE_NUMBER_P 0x0400
+#define UNI_CAUSE_ATTR_P 0x0800
+#define UNI_CAUSE_PARAM_P 0x1000
+
+ enum uni_cause_loc loc;
+ enum uni_cause cause;
+
+ union {
+ struct {
+ enum uni_cause_pu pu;
+ enum uni_cause_na na;
+ enum uni_cause_cond cond;
+ } cond;
+ struct {
+ enum uni_cause_reason reason;
+ enum uni_cause_cond cond;
+ u_int user;
+ uint8_t ie;
+ } rej;
+ struct {
+ uint8_t ie[UNI_CAUSE_IE_N];
+ u_int len;
+ } ie;
+ struct {
+ uint8_t traffic[UNI_CAUSE_TRAFFIC_N];
+ u_int len;
+ } traffic;
+ struct {
+ uint16_t vpci;
+ uint16_t vci;
+ } vpci;
+ uint8_t mtype;
+ u_char timer[3];
+ struct uni_ie_tns tns;
+ struct uni_ie_called number; /* TNS does not fit */
+ uint8_t param;
+ struct {
+ u_int nattr;
+ u_char attr[UNI_CAUSE_ATTR_N][3];
+ } attr;
+ } u;
+};
+enum uni_diag uni_diag(enum uni_cause, enum uni_coding);
+
+/* return a string for the cause (NULL if the coding/cause are illegal) */
+const char *uni_ie_cause2str(enum uni_coding, u_int);
+
+/*************************************************************************
+ *
+ * Connection identifier information element
+ */
+enum uni_connid_type {
+ UNI_CONNID_VCI = 0,
+ UNI_CONNID_ANYVCI = 1,
+ UNI_CONNID_NOVCI = 4,
+};
+enum uni_connid_assoc {
+ UNI_CONNID_ASSOC = 0,
+ UNI_CONNID_NONASSOC = 1,
+};
+struct uni_ie_connid {
+ struct uni_iehdr h;
+ enum uni_connid_assoc assoc;
+ enum uni_connid_type type;
+ u_int vpci : 16;
+ u_int vci : 16;
+};
+
+/*************************************************************************
+ *
+ * End point reference IE
+ */
+struct uni_ie_epref {
+ struct uni_iehdr h;
+ u_int flag : 1;
+ u_int epref : 15;
+};
+
+/*************************************************************************
+ *
+ * End point state IE
+ */
+enum uni_epstate {
+ UNI_EPSTATE_NULL = 0x00,
+ UNI_EPSTATE_ADD_INIT = 0x01,
+ UNI_EPSTATE_ALERT_DLVD = 0x04,
+ UNI_EPSTATE_ADD_RCVD = 0x06,
+ UNI_EPSTATE_ALERT_RCVD = 0x07,
+ UNI_EPSTATE_ACTIVE = 0x0a,
+ UNI_EPSTATE_DROP_INIT = 0x0b,
+ UNI_EPSTATE_DROP_RCVD = 0x0c,
+};
+
+struct uni_ie_epstate {
+ struct uni_iehdr h;
+ enum uni_epstate state;
+};
+
+/*************************************************************************
+ *
+ * Q.2932 Facility IE
+ */
+enum {
+ UNI_FACILITY_ROSE = 0x11,
+
+ UNI_FACILITY_MAXAPDU = 128,
+};
+
+struct uni_ie_facility {
+ struct uni_iehdr h;
+
+ u_char proto;
+ u_char apdu[UNI_FACILITY_MAXAPDU];
+ u_int len;
+};
+
+/*************************************************************************
+ *
+ * Notification indicator
+ */
+enum {
+ UNI_NOTIFY_MAXLEN = 128, /* maximum info length */
+};
+struct uni_ie_notify {
+ struct uni_iehdr h;
+ u_int len;
+ u_char notify[UNI_NOTIFY_MAXLEN];
+};
+
+/*************************************************************************
+ *
+ * QoS information element
+ */
+enum uni_qos {
+ UNI_QOS_CLASS0 = 0x00,
+ UNI_QOS_CLASS1 = 0x01,
+ UNI_QOS_CLASS2 = 0x02,
+ UNI_QOS_CLASS3 = 0x03,
+ UNI_QOS_CLASS4 = 0x04,
+};
+
+struct uni_ie_qos {
+ struct uni_iehdr h;
+ enum uni_qos fwd;
+ enum uni_qos bwd;
+};
+
+/*************************************************************************
+ *
+ * Broadband repeat indicator information element
+ */
+enum uni_repeat_type {
+ UNI_REPEAT_PRIDESC = 0x02,
+ UNI_REPEAT_STACK = 0x0a, /* PNNI */
+};
+
+struct uni_ie_repeat {
+ struct uni_iehdr h;
+ enum uni_repeat_type type;
+};
+
+/*************************************************************************
+ *
+ * Restart indicator information element
+ */
+enum uni_restart_type {
+ UNI_RESTART_CHANNEL = 0x0,
+ UNI_RESTART_PATH = 0x1,
+ UNI_RESTART_ALL = 0x2,
+};
+
+struct uni_ie_restart {
+ struct uni_iehdr h;
+ enum uni_restart_type rclass;
+};
+
+/*************************************************************************
+ *
+ * Broadband sending complete indicator information element
+ */
+struct uni_ie_scompl {
+ struct uni_iehdr h;
+};
+
+/*************************************************************************
+ *
+ * ATM traffic descriptor information element
+ */
+enum {
+ UNI_TRAFFIC_FMDCR_ID = 0x00,
+ UNI_TRAFFIC_BMDCR_ID = 0x02,
+ UNI_TRAFFIC_FPCR0_ID = 0x82,
+ UNI_TRAFFIC_BPCR0_ID = 0x83,
+ UNI_TRAFFIC_FPCR1_ID = 0x84,
+ UNI_TRAFFIC_BPCR1_ID = 0x85,
+ UNI_TRAFFIC_FSCR0_ID = 0x88,
+ UNI_TRAFFIC_BSCR0_ID = 0x89,
+ UNI_TRAFFIC_FSCR1_ID = 0x90,
+ UNI_TRAFFIC_BSCR1_ID = 0x91,
+ UNI_TRAFFIC_FABR1_ID = 0x92,
+ UNI_TRAFFIC_BABR1_ID = 0x93,
+ UNI_TRAFFIC_FMBS0_ID = 0xa0,
+ UNI_TRAFFIC_BMBS0_ID = 0xa1,
+ UNI_TRAFFIC_FMBS1_ID = 0xb0,
+ UNI_TRAFFIC_BMBS1_ID = 0xb1,
+ UNI_TRAFFIC_BEST_ID = 0xbe,
+ UNI_TRAFFIC_MOPT_ID = 0xbf,
+
+ UNI_TRAFFIC_FTAG = 0x01,
+ UNI_TRAFFIC_BTAG = 0x02,
+ UNI_TRAFFIC_FDISC = 0x80,
+ UNI_TRAFFIC_BDISC = 0x40,
+
+ UNI_MINTRAFFIC_FPCR0_ID = 0x82,
+ UNI_MINTRAFFIC_BPCR0_ID = 0x83,
+ UNI_MINTRAFFIC_FPCR1_ID = 0x84,
+ UNI_MINTRAFFIC_BPCR1_ID = 0x85,
+ UNI_MINTRAFFIC_FABR1_ID = 0x92,
+ UNI_MINTRAFFIC_BABR1_ID = 0x93,
+
+ UNI_MDCR_ORIGIN_USER = 0x00,
+ UNI_MDCR_ORIGIN_NET = 0x01,
+};
+
+#define UNI_TRAFFIC_FPCR0_P 0x0001
+#define UNI_TRAFFIC_BPCR0_P 0x0002
+#define UNI_TRAFFIC_FPCR1_P 0x0004
+#define UNI_TRAFFIC_BPCR1_P 0x0008
+#define UNI_TRAFFIC_FSCR0_P 0x0010
+#define UNI_TRAFFIC_BSCR0_P 0x0020
+#define UNI_TRAFFIC_FSCR1_P 0x0040
+#define UNI_TRAFFIC_BSCR1_P 0x0080
+#define UNI_TRAFFIC_FMBS0_P 0x0100
+#define UNI_TRAFFIC_BMBS0_P 0x0200
+#define UNI_TRAFFIC_FMBS1_P 0x0400
+#define UNI_TRAFFIC_BMBS1_P 0x0800
+#define UNI_TRAFFIC_BEST_P 0x1000
+#define UNI_TRAFFIC_MOPT_P 0x2000
+#define UNI_TRAFFIC_FABR1_P 0x4000
+#define UNI_TRAFFIC_BABR1_P 0x8000
+struct uni_xtraffic {
+ u_int fpcr0, bpcr0;
+ u_int fpcr1, bpcr1;
+ u_int fscr0, bscr0;
+ u_int fscr1, bscr1;
+ u_int fmbs0, bmbs0;
+ u_int fmbs1, bmbs1;
+ u_int fabr1, babr1;
+ u_int ftag, btag;
+ u_int fdisc, bdisc;
+};
+
+struct uni_ie_traffic {
+ struct uni_iehdr h;
+ struct uni_xtraffic t;
+};
+struct uni_ie_atraffic {
+ struct uni_iehdr h;
+ struct uni_xtraffic t;
+};
+
+/*
+ * Q.2961 minimum traffic descriptor
+ */
+struct uni_ie_mintraffic {
+ struct uni_iehdr h;
+#define UNI_MINTRAFFIC_FPCR0_P 0x0001
+#define UNI_MINTRAFFIC_BPCR0_P 0x0002
+#define UNI_MINTRAFFIC_FPCR1_P 0x0004
+#define UNI_MINTRAFFIC_BPCR1_P 0x0008
+#define UNI_MINTRAFFIC_FABR1_P 0x0010
+#define UNI_MINTRAFFIC_BABR1_P 0x0020
+
+ u_int fpcr0, bpcr0;
+ u_int fpcr1, bpcr1;
+ u_int fabr1, babr1;
+};
+
+/*
+ * UNI4.0+ (af-cs-0147.000) Minimum Desired Cell Rate
+ */
+struct uni_ie_mdcr {
+ struct uni_iehdr h;
+ u_int origin;
+ u_int fmdcr, bmdcr;
+};
+
+/*************************************************************************
+ *
+ * User-user information information element
+ */
+struct uni_ie_uu {
+ struct uni_iehdr h;
+ u_int len;
+ u_char uu[UNI_UU_MAXLEN];
+};
+
+/*************************************************************************
+ *
+ * Generic identifier transport
+ */
+enum uni_git_std {
+ UNI_GIT_STD_DSMCC = 0x01, /* DSM-CC */
+ UNI_GIT_STD_H245 = 0x02, /* H.245 */
+};
+enum uni_git_type {
+ UNI_GIT_TYPE_SESS = 0x01, /* session id */
+ UNI_GIT_TYPE_RES = 0x02, /* resource id */
+};
+
+enum {
+ UNI_GIT_MAXSESS = 20, /* max session value length */
+ UNI_GIT_MAXRES = 4, /* max resource value length */
+
+ UNI_GIT_MAXVAL = 20, /* the maximum of the above */
+ UNI_GIT_MAXSUB = 2, /* maximum number of og. 6 */
+};
+
+struct uni_ie_git {
+ struct uni_iehdr h;
+
+ enum uni_git_std std; /* identifier related standard/application */
+ u_int numsub;
+ struct {
+ enum uni_git_type type;
+ u_int len;
+ u_char val[UNI_GIT_MAXVAL];
+ } sub[UNI_GIT_MAXSUB];
+};
+
+/*************************************************************************
+ *
+ * End-to-end transit delay
+ */
+enum {
+ UNI_EETD_CTD_ID = 0x01, /* cumulative transit delay */
+ UNI_EETD_MTD_ID = 0x03, /* maximum transit delay */
+ UNI_EETD_NET_ID = 0x0a, /* network generated */
+ UNI_EETD_PMTD_ID = 0x0b, /* PNNI acceptable forward maximum ctd */
+ UNI_EETD_PCTD_ID = 0x11, /* PNNI cumulative forward maximum ctd */
+
+ UNI_EETD_ANYMAX = 0xffff,
+ UNI_EETD_MAXVAL = 0xffff, /* maximum value */
+};
+
+struct uni_ie_eetd {
+ struct uni_iehdr h;
+#define UNI_EETD_CUM_P 0x0001
+#define UNI_EETD_MAX_P 0x0002
+#define UNI_EETD_NET_P 0x0004 /* UNI4.0 9.1.2.1 */
+#define UNI_EETD_PMTD_P 0x0008 /* PNNI1.0 6.4.5.24 */
+#define UNI_EETD_PCTD_P 0x0010 /* PNNI1.0 6.4.5.24 */
+
+ u_int cumulative;
+ u_int maximum;
+ u_int pmtd;
+ u_int pctd;
+};
+
+/*************************************************************************
+ *
+ * Leaf-initiated-join call identifier
+ */
+enum uni_lij_idtype {
+ UNI_LIJ_IDTYPE_ROOT = 0x0, /* root created */
+};
+
+struct uni_ie_lij_callid {
+ struct uni_iehdr h;
+
+ enum uni_lij_idtype type;
+ u_int callid;
+};
+
+/*
+ * LIJ parameters
+ */
+enum uni_lij_screen {
+ UNI_LIJ_SCREEN_NETJOIN = 0x0, /* without root notification */
+};
+
+struct uni_ie_lij_param {
+ struct uni_iehdr h;
+
+ enum uni_lij_screen screen;
+};
+
+/*
+ * LIJ sequence number
+ */
+struct uni_ie_lij_seqno {
+ struct uni_iehdr h;
+
+ u_int seqno;
+};
+
+/*************************************************************************
+ *
+ * Locking/Non-locking shift not supported
+ */
+struct uni_ie_lshift {
+ struct uni_iehdr h;
+ u_int set:3;
+};
+
+struct uni_ie_nlshift {
+ struct uni_iehdr h;
+ u_int set:3;
+};
+
+/*************************************************************************
+ *
+ * Externded QoS information element
+ */
+enum {
+ UNI_EXQOS_FACC_ID = 0x94,
+ UNI_EXQOS_BACC_ID = 0x95,
+ UNI_EXQOS_FCUM_ID = 0x96,
+ UNI_EXQOS_BCUM_ID = 0x97,
+ UNI_EXQOS_FCLR_ID = 0xa2,
+ UNI_EXQOS_BCLR_ID = 0xa3,
+};
+
+enum uni_exqos_origin {
+ UNI_EXQOS_USER = 0,
+ UNI_EXQOS_NET = 1,
+};
+
+enum {
+ UNI_EXQOS_ANY_CDV = 0xffffff,
+ UNI_EXQOS_ANY_CLR = 0xff,
+};
+
+struct uni_ie_exqos {
+ struct uni_iehdr h;
+#define UNI_EXQOS_FACC_P 0x0001
+#define UNI_EXQOS_BACC_P 0x0002
+#define UNI_EXQOS_FCUM_P 0x0004
+#define UNI_EXQOS_BCUM_P 0x0008
+#define UNI_EXQOS_FCLR_P 0x0010
+#define UNI_EXQOS_BCLR_P 0x0020
+
+ enum uni_exqos_origin origin;
+ u_int facc;
+ u_int bacc;
+ u_int fcum;
+ u_int bcum;
+ u_int fclr;
+ u_int bclr;
+};
+
+/*************************************************************************
+ *
+ * Additional ABR parameters
+ * ABR setup parameters
+ */
+enum {
+ UNI_ABRADD_FADD_ID = 0xc2,
+ UNI_ABRADD_BADD_ID = 0xc3,
+ UNI_ABRSETUP_FICR_ID = 0xc2,
+ UNI_ABRSETUP_BICR_ID = 0xc3,
+ UNI_ABRSETUP_FTBE_ID = 0xc4,
+ UNI_ABRSETUP_BTBE_ID = 0xc5,
+ UNI_ABRSETUP_RMFRT_ID = 0xc6,
+ UNI_ABRSETUP_FRIF_ID = 0xc8,
+ UNI_ABRSETUP_BRIF_ID = 0xc9,
+ UNI_ABRSETUP_FRDF_ID = 0xca,
+ UNI_ABRSETUP_BRDF_ID = 0xcb,
+};
+
+struct uni_abr_rec {
+ u_int present;
+#define UNI_ABR_REC_NRM_P 0x80000000
+#define UNI_ABR_REC_TRM_P 0x40000000
+#define UNI_ABR_REC_CDF_P 0x20000000
+#define UNI_ABR_REC_ADTF_P 0x10000000
+ u_int nrm:3;
+ u_int trm:3;
+ u_int cdf:3;
+ u_int adtf:10;
+};
+
+struct uni_ie_abradd {
+ struct uni_iehdr h;
+ struct uni_abr_rec fwd, bwd;
+};
+
+struct uni_ie_abrsetup {
+ struct uni_iehdr h;
+#define UNI_ABRSETUP_FICR_P 0x0001
+#define UNI_ABRSETUP_BICR_P 0x0002
+#define UNI_ABRSETUP_FTBE_P 0x0004
+#define UNI_ABRSETUP_BTBE_P 0x0008
+#define UNI_ABRSETUP_FRIF_P 0x0010
+#define UNI_ABRSETUP_BRIF_P 0x0020
+#define UNI_ABRSETUP_FRDF_P 0x0040
+#define UNI_ABRSETUP_BRDF_P 0x0080
+#define UNI_ABRSETUP_RMFRT_P 0x0100
+
+ u_int ficr, bicr;
+ u_int ftbe, btbe;
+ u_int rmfrt;
+ u_int frif, brif;
+ u_int frdf, brdf;
+};
+
+/*************************************************************************
+ *
+ * Connection scope information element
+ */
+enum uni_cscope {
+ UNI_CSCOPE_ORG = 0x01,
+};
+
+enum {
+ UNI_CSCOPE_ORG_LOC = 0x01,
+ UNI_CSCOPE_ORG_LOC_P1 = 0x02,
+ UNI_CSCOPE_ORG_LOC_P2 = 0x03,
+ UNI_CSCOPE_ORG_SITE_M1 = 0x04,
+ UNI_CSCOPE_ORG_SITE = 0x05,
+ UNI_CSCOPE_ORG_SITE_P1 = 0x06,
+ UNI_CSCOPE_ORG_ORG_M1 = 0x07,
+ UNI_CSCOPE_ORG_ORG = 0x08,
+ UNI_CSCOPE_ORG_ORG_P1 = 0x09,
+ UNI_CSCOPE_ORG_COMM_M1 = 0x0a,
+ UNI_CSCOPE_ORG_COMM = 0x0b,
+ UNI_CSCOPE_ORG_COMM_P1 = 0x0c,
+ UNI_CSCOPE_ORG_REG = 0x0d,
+ UNI_CSCOPE_ORG_INTER = 0x0e,
+ UNI_CSCOPE_ORG_GLOBAL = 0x0f,
+};
+
+struct uni_ie_cscope {
+ struct uni_iehdr h;
+ enum uni_cscope type;
+ u_int scope:8;
+};
+
+/*************************************************************************
+ *
+ * Connection scope information element
+ */
+enum uni_report {
+ UNI_REPORT_MODCONF = 0x01,
+ UNI_REPORT_CLOCK = 0x02,
+ UNI_REPORT_EEAVAIL = 0x04,
+ UNI_REPORT_EEREQ = 0x05,
+ UNI_REPORT_EECOMPL = 0x06,
+};
+
+struct uni_ie_report {
+ struct uni_iehdr h;
+ enum uni_report report;
+};
+
+/*************************************************************************
+ *
+ * PNNI Designated transit list information element
+ */
+enum {
+ UNI_DTL_LOGNP = 0x01,
+ UNI_DTL_LOGNP_SIZE = 27,
+};
+
+struct uni_ie_dtl {
+ struct uni_iehdr h;
+ u_int ptr:16;
+ u_int num;
+ struct {
+ u_char node_level;
+ u_char node_id[21];
+ u_int port_id;
+ } dtl[UNI_DTL_MAXNUM];
+};
+
+/*************************************************************************
+ *
+ * PNNI Crankback information element
+ */
+enum uni_crankback {
+ UNI_CRANKBACK_IF = 0x02,
+ UNI_CRANKBACK_NODE = 0x03,
+ UNI_CRANKBACK_LINK = 0x04,
+};
+
+enum {
+ UNI_CAUSE_NXNODE_UNREACH = 128,
+ UNI_CAUSE_DTL_NOT_MY_ID = 160,
+};
+
+struct uni_ie_crankback {
+ struct uni_iehdr h;
+#define UNI_CRANKBACK_TOP_P 0x0001
+#define UNI_CRANKBACK_TOPX_P 0x0002
+#define UNI_CRANKBACK_QOS_P 0x0004
+ u_int level:8;
+ enum uni_crankback type;
+ union {
+ struct {
+ u_char level;
+ u_char id[21];
+ } node;
+ struct {
+ u_char plevel;
+ u_char pid[21];
+ u_int port;
+ u_char slevel;
+ u_char sid[21];
+ } link;
+ } id;
+ u_int cause:8;
+ union {
+ struct {
+ u_int dir:8;
+ u_int port;
+ u_int avcr;
+ u_int crm;
+ u_int vf;
+ } top;
+ struct {
+ u_int ctd:1;
+ u_int cdv:1;
+ u_int clr:1;
+ u_int other:1;
+ } qos;
+ } diag;
+};
+
+/*************************************************************************
+ *
+ * PNNI Call_ing/called party soft PVPC/PVCC information element
+ */
+enum uni_soft_sel {
+ UNI_SOFT_SEL_ANY = 0x00,
+ UNI_SOFT_SEL_REQ = 0x02,
+ UNI_SOFT_SEL_ASS = 0x04,
+};
+
+struct uni_ie_calling_soft {
+ struct uni_iehdr h;
+#define UNI_CALLING_SOFT_VCI_P 0x0001
+ u_int vpi:12;
+ u_int vci:16;
+};
+struct uni_ie_called_soft {
+ struct uni_iehdr h;
+#define UNI_CALLED_SOFT_VPI_P 0x0001
+#define UNI_CALLED_SOFT_VCI_P 0x0002
+ enum uni_soft_sel sel;
+ u_int vpi:12;
+ u_int vci:16;
+};
+
+/*************************************************************************/
+
+#include <netnatm/msg/uni_ie.h>
+#include <netnatm/msg/uni_msg.h>
+
+struct uni_all {
+ enum uni_msgtype mtype;
+ union uni_msgall u;
+};
+
+struct uni_ie {
+ enum uni_ietype ietype;
+ union uni_ieall u;
+};
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/saal/saal_sscfu.c b/sys/contrib/ngatm/netnatm/saal/saal_sscfu.c
new file mode 100644
index 000000000000..80140ba03d49
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/saal/saal_sscfu.c
@@ -0,0 +1,577 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/saal/saal_sscfu.c,v 1.4 2004/07/08 08:22:10 brandt Exp $
+ *
+ * SSCF on the UNI
+ */
+
+#include <netnatm/saal/sscfu.h>
+#include <netnatm/saal/sscfupriv.h>
+
+#define MKSTR(S) #S
+
+static const char *const sscf_sigs[] = {
+ MKSTR(SAAL_ESTABLISH_request),
+ MKSTR(SAAL_ESTABLISH_indication),
+ MKSTR(SAAL_ESTABLISH_confirm),
+ MKSTR(SAAL_RELEASE_request),
+ MKSTR(SAAL_RELEASE_confirm),
+ MKSTR(SAAL_RELEASE_indication),
+ MKSTR(SAAL_DATA_request),
+ MKSTR(SAAL_DATA_indication),
+ MKSTR(SAAL_UDATA_request),
+ MKSTR(SAAL_UDATA_indication),
+};
+
+static const char *const sscf_states[] = {
+ MKSTR(SSCF_RELEASED),
+ MKSTR(SSCF_AWAITING_ESTABLISH),
+ MKSTR(SSCF_AWAITING_RELEASE),
+ MKSTR(SSCF_ESTABLISHED),
+ MKSTR(SSCF_RESYNC),
+};
+
+#define AA_SIG(S,G,M) \
+ ((S)->funcs->send_upper((S), (S)->aarg, (G), (M)))
+
+#define SSCOP_AASIG(S,G,M,P) \
+ ((S)->funcs->send_lower((S), (S)->aarg, (G), (M), (P)))
+
+MEMINIT();
+
+static void sscfu_unqueue(struct sscfu *sscf);
+
+/************************************************************/
+/*
+ * INSTANCE AND CLASS MANAGEMENT
+ */
+
+/*
+ * Initialize SSCF.
+ */
+struct sscfu *
+sscfu_create(void *a, const struct sscfu_funcs *funcs)
+{
+ struct sscfu *sscf;
+
+ MEMZALLOC(sscf, struct sscfu *, sizeof(struct sscfu));
+ if (sscf == NULL)
+ return (NULL);
+
+ sscf->funcs = funcs;
+ sscf->aarg = a;
+ sscf->state = SSCFU_RELEASED;
+ sscf->inhand = 0;
+ SIGQ_INIT(&sscf->sigs);
+ sscf->debug = 0;
+
+ return (sscf);
+}
+
+/*
+ * Reset the instance. Call only if you know, what you're doing.
+ */
+void
+sscfu_reset(struct sscfu *sscf)
+{
+ sscf->state = SSCFU_RELEASED;
+ sscf->inhand = 0;
+ SIGQ_CLEAR(&sscf->sigs);
+}
+
+/*
+ * Destroy SSCF
+ */
+void
+sscfu_destroy(struct sscfu *sscf)
+{
+ SIGQ_CLEAR(&sscf->sigs);
+ MEMFREE(sscf);
+}
+
+enum sscfu_state
+sscfu_getstate(const struct sscfu *sscf)
+{
+ return (sscf->state);
+}
+
+u_int
+sscfu_getdefparam(struct sscop_param *p)
+{
+ memset(p, 0, sizeof(*p));
+
+ p->timer_cc = 1000;
+ p->timer_poll = 750;
+ p->timer_keep_alive = 2000;
+ p->timer_no_response = 7000;
+ p->timer_idle = 15000;
+ p->maxk = 4096;
+ p->maxj = 4096;
+ p->maxcc = 4;
+ p->maxpd = 25;
+
+ return (SSCOP_SET_TCC | SSCOP_SET_TPOLL | SSCOP_SET_TKA |
+ SSCOP_SET_TNR | SSCOP_SET_TIDLE | SSCOP_SET_MAXK |
+ SSCOP_SET_MAXJ | SSCOP_SET_MAXCC | SSCOP_SET_MAXPD);
+}
+
+const char *
+sscfu_signame(enum saal_sig sig)
+{
+ static char str[40];
+
+ if (sig >= sizeof(sscf_sigs)/sizeof(sscf_sigs[0])) {
+ sprintf(str, "BAD SAAL_SIGNAL %u", sig);
+ return (str);
+ } else {
+ return (sscf_sigs[sig]);
+ }
+}
+
+const char *
+sscfu_statename(enum sscfu_state s)
+{
+ static char str[40];
+
+ if (s >= sizeof(sscf_states)/sizeof(sscf_states[0])) {
+ sprintf(str, "BAD SSCFU state %u", s);
+ return (str);
+ } else {
+ return (sscf_states[s]);
+ }
+}
+
+/************************************************************/
+/*
+ * EXTERNAL INPUT SIGNAL MAPPING
+ */
+static __inline void
+set_state(struct sscfu *sscf, enum sscfu_state state)
+{
+ VERBOSE(sscf, SSCFU_DBG_STATE, (sscf, sscf->aarg,
+ "change state from %s to %s",
+ sscf_states[sscf->state], sscf_states[state]));
+ sscf->state = state;
+}
+
+/*
+ * signal from SSCOP to SSCF
+ * Message must be freed by the user specified handler, if
+ * it is passed.
+ */
+void
+sscfu_input(struct sscfu *sscf, enum sscop_aasig sig,
+ struct SSCFU_MBUF_T *m, u_int arg __unused)
+{
+ sscf->inhand = 1;
+
+ VERBOSE(sscf, SSCFU_DBG_LSIG, (sscf, sscf->aarg,
+ "SSCF got signal %d. in state %s", sig, sscf_states[sscf->state]));
+
+ switch (sig) {
+
+ case SSCOP_RELEASE_indication:
+ /* arg is: UU, SRC */
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+
+ case SSCFU_AWAITING_ESTABLISH:
+ set_state(sscf, SSCFU_RELEASED);
+ AA_SIG(sscf, SAAL_RELEASE_indication, m);
+ break;
+
+ case SSCFU_AWAITING_RELEASE:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+
+ case SSCFU_ESTABLISHED:
+ set_state(sscf, SSCFU_RELEASED);
+ AA_SIG(sscf, SAAL_RELEASE_indication, m);
+ break;
+
+ case SSCFU_RESYNC:
+ set_state(sscf, SSCFU_RELEASED);
+ AA_SIG(sscf, SAAL_RELEASE_indication, m);
+ break;
+ }
+ break;
+
+ case SSCOP_ESTABLISH_indication:
+ /* arg is: UU */
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ set_state(sscf, SSCFU_ESTABLISHED);
+ SSCOP_AASIG(sscf, SSCOP_ESTABLISH_response, NULL, 1);
+ AA_SIG(sscf, SAAL_ESTABLISH_indication, m);
+ break;
+
+ case SSCFU_AWAITING_ESTABLISH:
+ case SSCFU_AWAITING_RELEASE:
+ case SSCFU_ESTABLISHED:
+ case SSCFU_RESYNC:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+ }
+ break;
+
+ case SSCOP_ESTABLISH_confirm:
+ /* arg is: UU */
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+
+ case SSCFU_AWAITING_ESTABLISH:
+ set_state(sscf, SSCFU_ESTABLISHED);
+ AA_SIG(sscf, SAAL_ESTABLISH_confirm, m);
+ break;
+
+ case SSCFU_AWAITING_RELEASE:
+ case SSCFU_ESTABLISHED:
+ case SSCFU_RESYNC:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+ }
+ break;
+
+ case SSCOP_RELEASE_confirm:
+ /* arg is: */
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ case SSCFU_AWAITING_ESTABLISH:
+ goto badsig;
+
+ case SSCFU_AWAITING_RELEASE:
+ set_state(sscf, SSCFU_RELEASED);
+ AA_SIG(sscf, SAAL_RELEASE_confirm, NULL);
+ break;
+
+ case SSCFU_ESTABLISHED:
+ case SSCFU_RESYNC:
+ goto badsig;
+ }
+ break;
+
+ case SSCOP_DATA_indication:
+ /* arg is: MU */
+ sscf->funcs->window(sscf, sscf->aarg, 1);
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ case SSCFU_AWAITING_ESTABLISH:
+ case SSCFU_AWAITING_RELEASE:
+ MBUF_FREE(m);
+ goto badsig;
+
+ case SSCFU_ESTABLISHED:
+ AA_SIG(sscf, SAAL_DATA_indication, m);
+ break;
+
+ case SSCFU_RESYNC:
+ MBUF_FREE(m);
+ goto badsig;
+ }
+ break;
+
+ case SSCOP_RECOVER_indication:
+ /* arg is: */
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ case SSCFU_AWAITING_ESTABLISH:
+ case SSCFU_AWAITING_RELEASE:
+ goto badsig;
+
+ case SSCFU_ESTABLISHED:
+ SSCOP_AASIG(sscf, SSCOP_RECOVER_response, NULL, 0);
+ AA_SIG(sscf, SAAL_ESTABLISH_indication, NULL);
+ break;
+
+ case SSCFU_RESYNC:
+ goto badsig;
+ }
+ break;
+
+ case SSCOP_RESYNC_indication:
+ /* arg is: UU */
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ case SSCFU_AWAITING_ESTABLISH:
+ case SSCFU_AWAITING_RELEASE:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+
+ case SSCFU_ESTABLISHED:
+ SSCOP_AASIG(sscf, SSCOP_RESYNC_response, NULL, 0);
+ AA_SIG(sscf, SAAL_ESTABLISH_indication, m);
+ break;
+
+ case SSCFU_RESYNC:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+ }
+ break;
+
+ case SSCOP_RESYNC_confirm:
+ /* arg is: */
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ case SSCFU_AWAITING_ESTABLISH:
+ case SSCFU_AWAITING_RELEASE:
+ case SSCFU_ESTABLISHED:
+
+ case SSCFU_RESYNC:
+ set_state(sscf, SSCFU_ESTABLISHED);
+ AA_SIG(sscf, SAAL_ESTABLISH_confirm, NULL);
+ break;
+ }
+ break;
+
+ case SSCOP_UDATA_indication:
+ /* arg is: MD */
+ AA_SIG(sscf, SAAL_UDATA_indication, m);
+ break;
+
+
+ case SSCOP_RETRIEVE_indication:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+
+ case SSCOP_RETRIEVE_COMPL_indication:
+ goto badsig;
+
+ case SSCOP_ESTABLISH_request:
+ case SSCOP_RELEASE_request:
+ case SSCOP_ESTABLISH_response:
+ case SSCOP_DATA_request:
+ case SSCOP_RECOVER_response:
+ case SSCOP_RESYNC_request:
+ case SSCOP_RESYNC_response:
+ case SSCOP_UDATA_request:
+ case SSCOP_RETRIEVE_request:
+ ASSERT(0);
+ break;
+ }
+
+ sscfu_unqueue(sscf);
+ return;
+
+ badsig:
+ VERBOSE(sscf, SSCFU_DBG_ERR, (sscf, sscf->aarg,
+ "bad signal %d. in state %s", sig, sscf_states[sscf->state]));
+ sscfu_unqueue(sscf);
+}
+
+
+/*
+ * Handle signals from the user
+ */
+static void
+sscfu_dosig(struct sscfu *sscf, enum saal_sig sig, struct SSCFU_MBUF_T *m)
+{
+ VERBOSE(sscf, SSCFU_DBG_EXEC, (sscf, sscf->aarg,
+ "executing signal %s(%s)",
+ sscf_sigs[sig], sscf_states[sscf->state]));
+
+ switch (sig) {
+
+ case SAAL_ESTABLISH_request:
+ /* arg is opt UU */
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ set_state(sscf, SSCFU_AWAITING_ESTABLISH);
+ SSCOP_AASIG(sscf, SSCOP_ESTABLISH_request, m, 1);
+ break;
+
+ case SSCFU_AWAITING_ESTABLISH:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+
+ case SSCFU_AWAITING_RELEASE:
+ set_state(sscf, SSCFU_AWAITING_ESTABLISH);
+ SSCOP_AASIG(sscf, SSCOP_ESTABLISH_request, m, 1);
+ break;
+
+ case SSCFU_ESTABLISHED:
+ set_state(sscf, SSCFU_RESYNC);
+ SSCOP_AASIG(sscf, SSCOP_RESYNC_request, m, 0);
+ break;
+
+ case SSCFU_RESYNC:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+ }
+ break;
+
+ case SAAL_RELEASE_request:
+ /* arg is opt UU */
+ switch(sscf->state) {
+
+ case SSCFU_RELEASED:
+ if (m)
+ MBUF_FREE(m);
+ AA_SIG(sscf, SAAL_RELEASE_confirm, NULL);
+ break;
+
+ case SSCFU_AWAITING_ESTABLISH:
+ set_state(sscf, SSCFU_AWAITING_RELEASE);
+ SSCOP_AASIG(sscf, SSCOP_RELEASE_request, m, 0);
+ break;
+
+ case SSCFU_AWAITING_RELEASE:
+ if (m)
+ MBUF_FREE(m);
+ goto badsig;
+
+ case SSCFU_ESTABLISHED:
+ set_state(sscf, SSCFU_AWAITING_RELEASE);
+ SSCOP_AASIG(sscf, SSCOP_RELEASE_request, m, 0);
+ break;
+
+ case SSCFU_RESYNC:
+ set_state(sscf, SSCFU_AWAITING_RELEASE);
+ SSCOP_AASIG(sscf, SSCOP_RELEASE_request, m, 0);
+ break;
+ }
+ break;
+
+ case SAAL_DATA_request:
+ /* arg is DATA */
+ switch (sscf->state) {
+
+ case SSCFU_RELEASED:
+ case SSCFU_AWAITING_ESTABLISH:
+ case SSCFU_AWAITING_RELEASE:
+ MBUF_FREE(m);
+ goto badsig;
+
+ case SSCFU_ESTABLISHED:
+ SSCOP_AASIG(sscf, SSCOP_DATA_request, m, 0);
+ break;
+
+ case SSCFU_RESYNC:
+ MBUF_FREE(m);
+ goto badsig;
+ }
+ break;
+
+ case SAAL_UDATA_request:
+ /* arg is UDATA */
+ SSCOP_AASIG(sscf, SSCOP_UDATA_request, m, 0);
+ break;
+
+ case SAAL_ESTABLISH_indication:
+ case SAAL_ESTABLISH_confirm:
+ case SAAL_RELEASE_confirm:
+ case SAAL_RELEASE_indication:
+ case SAAL_DATA_indication:
+ case SAAL_UDATA_indication:
+ ASSERT(0);
+ break;
+ }
+ return;
+
+ badsig:
+ VERBOSE(sscf, SSCFU_DBG_ERR, (sscf, sscf->aarg,
+ "bad signal %s in state %s", sscf_sigs[sig],
+ sscf_states[sscf->state]));
+}
+
+/*
+ * Handle user signal.
+ */
+int
+sscfu_saalsig(struct sscfu *sscf, enum saal_sig sig, struct SSCFU_MBUF_T *m)
+{
+ struct sscfu_sig *s;
+
+ if (sscf->inhand) {
+ VERBOSE(sscf, SSCFU_DBG_EXEC, (sscf, sscf->aarg,
+ "queuing user signal %s(%s)",
+ sscf_sigs[sig], sscf_states[sscf->state]));
+ SIG_ALLOC(s);
+ if (s == NULL)
+ return (ENOMEM);
+ s->sig = sig;
+ s->m = m;
+ SIGQ_APPEND(&sscf->sigs, s);
+ return (0);
+ }
+
+ sscf->inhand = 1;
+ sscfu_dosig(sscf, sig, m);
+ sscfu_unqueue(sscf);
+ return (0);
+}
+
+/*
+ * Unqueue all qeueued signals. Must be called with inhand==1.
+ */
+static void
+sscfu_unqueue(struct sscfu *sscf)
+{
+ struct sscfu_sig *s;
+
+ while ((s = SIGQ_GET(&sscf->sigs)) != NULL) {
+ sscfu_dosig(sscf, s->sig, s->m);
+ SIG_FREE(s);
+ }
+ sscf->inhand = 0;
+}
+
+void
+sscfu_setdebug(struct sscfu *sscf, u_int n)
+{
+ sscf->debug = n;
+}
+
+u_int
+sscfu_getdebug(const struct sscfu *sscf)
+{
+ return (sscf->debug);
+}
diff --git a/sys/contrib/ngatm/netnatm/saal/saal_sscop.c b/sys/contrib/ngatm/netnatm/saal/saal_sscop.c
new file mode 100644
index 000000000000..0776eda9e4f0
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/saal/saal_sscop.c
@@ -0,0 +1,4946 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $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)
+ */
+
+#include <netnatm/saal/sscop.h>
+#include <netnatm/saal/sscoppriv.h>
+
+#ifndef FAILURE
+#define FAILURE(S)
+#endif
+
+#define MKSTR(S) #S
+
+static const char *const sscop_sigs[] = {
+ MKSTR(SSCOP_ESTABLISH_request),
+ MKSTR(SSCOP_ESTABLISH_indication),
+ MKSTR(SSCOP_ESTABLISH_response),
+ MKSTR(SSCOP_ESTABLISH_confirm),
+ MKSTR(SSCOP_RELEASE_request),
+ MKSTR(SSCOP_RELEASE_indication),
+ MKSTR(SSCOP_RELEASE_confirm),
+ MKSTR(SSCOP_DATA_request),
+ MKSTR(SSCOP_DATA_indication),
+ MKSTR(SSCOP_UDATA_request),
+ MKSTR(SSCOP_UDATA_indication),
+ MKSTR(SSCOP_RECOVER_indication),
+ MKSTR(SSCOP_RECOVER_response),
+ MKSTR(SSCOP_RESYNC_request),
+ MKSTR(SSCOP_RESYNC_indication),
+ MKSTR(SSCOP_RESYNC_response),
+ MKSTR(SSCOP_RESYNC_confirm),
+ MKSTR(SSCOP_RETRIEVE_request),
+ MKSTR(SSCOP_RETRIEVE_indication),
+ MKSTR(SSCOP_RETRIEVE_COMPL_indication),
+};
+
+static const char *const sscop_msigs[] = {
+ MKSTR(SSCOP_MDATA_request),
+ MKSTR(SSCOP_MDATA_indication),
+ MKSTR(SSCOP_MERROR_indication),
+};
+
+static const char *const states[] = {
+ MKSTR(SSCOP_IDLE),
+ MKSTR(SSCOP_OUT_PEND),
+ MKSTR(SSCOP_IN_PEND),
+ MKSTR(SSCOP_OUT_DIS_PEND),
+ MKSTR(SSCOP_OUT_RESYNC_PEND),
+ MKSTR(SSCOP_IN_RESYNC_PEND),
+ MKSTR(SSCOP_OUT_REC_PEND),
+ MKSTR(SSCOP_REC_PEND),
+ MKSTR(SSCOP_IN_REC_PEND),
+ MKSTR(SSCOP_READY),
+};
+
+#ifdef SSCOP_DEBUG
+static const char *const events[] = {
+ MKSTR(SIG_BGN),
+ MKSTR(SIG_BGAK),
+ MKSTR(SIG_END),
+ MKSTR(SIG_ENDAK),
+ MKSTR(SIG_RS),
+ MKSTR(SIG_RSAK),
+ MKSTR(SIG_BGREJ),
+ MKSTR(SIG_SD),
+ MKSTR(SIG_ER),
+ MKSTR(SIG_POLL),
+ MKSTR(SIG_STAT),
+ MKSTR(SIG_USTAT),
+ MKSTR(SIG_UD),
+ MKSTR(SIG_MD),
+ MKSTR(SIG_ERAK),
+
+ MKSTR(SIG_T_CC),
+ MKSTR(SIG_T_POLL),
+ MKSTR(SIG_T_KA),
+ MKSTR(SIG_T_NR),
+ MKSTR(SIG_T_IDLE),
+
+ MKSTR(SIG_PDU_Q),
+ MKSTR(SIG_USER_DATA),
+ MKSTR(SIG_ESTAB_REQ),
+ MKSTR(SIG_ESTAB_RESP),
+ MKSTR(SIG_RELEASE_REQ),
+ MKSTR(SIG_RECOVER),
+ MKSTR(SIG_SYNC_REQ),
+ MKSTR(SIG_SYNC_RESP),
+ MKSTR(SIG_UDATA),
+ MKSTR(SIG_MDATA),
+ MKSTR(SIG_UPDU_Q),
+ MKSTR(SIG_MPDU_Q),
+ MKSTR(SIG_RETRIEVE),
+};
+
+static const char *const pdus[] = {
+ "illegale PDU type 0", /* no PDU type 0 */
+ MKSTR(PDU_BGN),
+ MKSTR(PDU_BGAK),
+ MKSTR(PDU_END),
+ MKSTR(PDU_ENDAK),
+ MKSTR(PDU_RS),
+ MKSTR(PDU_RSAK),
+ MKSTR(PDU_BGREJ),
+ MKSTR(PDU_SD),
+ MKSTR(PDU_ER),
+ MKSTR(PDU_POLL),
+ MKSTR(PDU_STAT),
+ MKSTR(PDU_USTAT),
+ MKSTR(PDU_UD),
+ MKSTR(PDU_MD),
+ MKSTR(PDU_ERAK),
+};
+#endif
+
+MEMINIT();
+
+static void sscop_signal(struct sscop *, u_int, struct sscop_msg *);
+static void sscop_save_signal(struct sscop *, u_int, struct sscop_msg *);
+static void handle_sigs(struct sscop *);
+static void sscop_set_state(struct sscop *, u_int);
+
+/************************************************************/
+
+
+/************************************************************/
+/*
+ * Queue macros
+ */
+#define SSCOP_MSG_FREE(MSG) \
+ do { \
+ if(MSG) { \
+ MBUF_FREE((MSG)->m); \
+ MSG_FREE((MSG)); \
+ } \
+ } while(0)
+
+static inline struct sscop_msg *QFIND(sscop_msgq_head_t *q, u_int rn)
+{
+ struct sscop_msg *msg = NULL, *m;
+ MSGQ_FOREACH(m, q) {
+ if(m->seqno == rn) {
+ msg = m;
+ break;
+ }
+ }
+ return msg;
+}
+
+#define QINSERT(Q,M) \
+ do { \
+ struct sscop_msg *_msg = NULL, *_m; \
+ MSGQ_FOREACH(_m, (Q)) { \
+ if (_m->seqno > (M)->seqno) { \
+ _msg = _m; \
+ break; \
+ } \
+ } \
+ if (_msg != NULL) \
+ MSGQ_INSERT_BEFORE(_msg, (M)); \
+ else \
+ MSGQ_APPEND((Q), (M)); \
+ } while (0)
+
+
+/*
+ * Send an error indication to the management plane.
+ */
+#define MAAL_ERROR(S,E,C) \
+ do { \
+ VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \
+ "MAA-Signal %s in state %s", \
+ sscop_msigs[SSCOP_MERROR_indication], states[(S)->state])); \
+ (S)->funcs->send_manage((S), (S)->aarg, \
+ SSCOP_MERROR_indication, NULL, (E), (C)); \
+ } while(0)
+
+#define MAAL_DATA(S,M) \
+ do { \
+ VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \
+ "MAA-Signal %s in state %s", \
+ sscop_msigs[SSCOP_MDATA_indication], states[(S)->state])); \
+ (S)->funcs->send_manage((S), (S)->aarg, \
+ SSCOP_MDATA_indication, (M), 0, 0); \
+ } while(0)
+
+#define AAL_DATA(S,D,M,N) \
+ do { \
+ VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \
+ "AA-Signal %s in state %s", \
+ sscop_sigs[D], states[(S)->state])); \
+ (S)->funcs->send_upper((S), (S)->aarg, (D), (M), (N)); \
+ } while(0)
+
+#define AAL_SIG(S,D) \
+ do { \
+ VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \
+ "AA-Signal %s in state %s", \
+ sscop_sigs[D], states[(S)->state])); \
+ (S)->funcs->send_upper((S), (S)->aarg, (D), NULL, 0); \
+ } while(0)
+
+#ifdef SSCOP_DEBUG
+#define AAL_SEND(S,M) do { \
+ if (ISVERBOSE(S, SSCOP_DBG_PDU)) \
+ sscop_dump_pdu(S, "tx", (M)); \
+ (S)->funcs->send_lower((S), (S)->aarg, (M)); \
+ } while(0)
+#else
+#define AAL_SEND(S,M) (S)->funcs->send_lower((S), (S)->aarg, (M))
+#endif
+
+
+/*
+ * Free a save user-to-user data buffer and set the pointer to zero
+ * to signal, that it is free.
+ */
+#define FREE_UU(F) \
+ do { \
+ if(sscop->F) { \
+ MBUF_FREE(sscop->F); \
+ sscop->F = NULL; \
+ } \
+ } while(0)
+
+#define SET_UU(F,U) \
+ do { \
+ FREE_UU(F); \
+ sscop->F = U->m; \
+ U->m = NULL; \
+ SSCOP_MSG_FREE(U); \
+ } while(0)
+
+#define AAL_UU_SIGNAL(S, SIG, M, PL, SN) \
+ do { \
+ if(MBUF_LEN((M)->m) > 0) { \
+ MBUF_UNPAD((M)->m,(PL)); \
+ AAL_DATA((S), (SIG), (M)->m, (SN)); \
+ (M)->m = NULL; \
+ } else { \
+ AAL_DATA((S), (SIG), NULL, (SN)); \
+ } \
+ SSCOP_MSG_FREE((M)); \
+ } while(0)
+
+
+
+TIMER_FUNC(cc, CC)
+TIMER_FUNC(nr, NR)
+TIMER_FUNC(ka, KA)
+TIMER_FUNC(poll, POLL)
+TIMER_FUNC(idle, IDLE)
+
+/************************************************************/
+/*
+ * INSTANCE AND TYPE HANDLING.
+ */
+#ifdef SSCOP_DEBUG
+static void
+sscop_dump_pdu(struct sscop *sscop, const char *dir,
+ const struct SSCOP_MBUF_T *m)
+{
+ u_int32_t v1, v2, v3, v4;
+ u_int size = MBUF_LEN(m);
+ u_int n, i;
+
+ if (size < 8)
+ return;
+
+ v1 = MBUF_TRAIL32(m, -1);
+ v2 = MBUF_TRAIL32(m, -2);
+
+ switch ((v1 >> 24) & 0xf) {
+
+ case 0:
+ return;
+
+ case PDU_BGN:
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ "%s BGN n(mr)=%u n(sq)=%u pl=%u",
+ dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3);
+ return;
+
+ case PDU_BGAK:
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ "%s BGAK n(mr)=%u pl=%u",
+ dir, v1 & 0xffffff, (v1 >> 30) & 0x3);
+ return;
+
+ case PDU_END:
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ "%s END r=%u s=%u pl=%u",
+ dir, (v1 >> 29) & 1, (v1 >> 28) & 1, (v1 >> 30) & 0x3);
+ return;
+
+ case PDU_ENDAK:
+ sscop->funcs->verbose(sscop, sscop->aarg, "%s ENDAK", dir);
+ return;
+
+ case PDU_RS:
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ "%s RS n(mr)=%u n(sq)=%u pl=%u",
+ dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3);
+ return;
+
+ case PDU_RSAK:
+ sscop->funcs->verbose(sscop, sscop->aarg, "%s RSAK n(mr)=%u",
+ dir, v1 & 0xffffff);
+ return;
+
+ case PDU_BGREJ:
+ sscop->funcs->verbose(sscop, sscop->aarg, "%s BGREJ pl=%u",
+ dir, (v1 >> 30) & 0x3);
+ return;
+
+ case PDU_SD:
+ sscop->funcs->verbose(sscop, sscop->aarg, "%s SD n(s)=%u pl=%u",
+ dir, v1 & 0xffffff, (v1 >> 30) & 0x3);
+ return;
+
+ case PDU_ER:
+ sscop->funcs->verbose(sscop, sscop->aarg, "%s ER n(mr)=%u n(sq)=%u",
+ dir, v1 & 0xffffff, v2 & 0xff);
+ return;
+
+ case PDU_POLL:
+ sscop->funcs->verbose(sscop, sscop->aarg, "%s POLL n(s)=%u n(ps)=%u",
+ dir, v1 & 0xffffff, v2 & 0xffffff);
+ return;
+
+ case PDU_STAT:
+ if (size < 12)
+ return;
+ v3 = MBUF_TRAIL32(m, -3);
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ "%s STAT n(r)=%u n(mr)=%u n(ps)=%u",
+ dir, v1 & 0xffffff, v2 & 0xffffff, v3 & 0xffffff);
+ n = (size - 12) / 4;
+ for (i = 0; i < (size - 12) / 4; i++, n--) {
+ v4 = MBUF_TRAIL32(m, -4 - (int)i);
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ " LE(%u)=%u", n, v4 & 0xffffff);
+ }
+ return;
+
+ case PDU_USTAT:
+ if (size < 16)
+ return;
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ "%s STAT n(r)=%u n(mr)=%u LE1=%u LE2=%u",
+ dir, v1 & 0xffffff, v2 & 0xffffff,
+ MBUF_TRAIL32(m, -4) & 0xffffff,
+ MBUF_TRAIL32(m, -3) & 0xffffff);
+ return;
+
+ case PDU_UD:
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ "%s UD pl=%u", dir, (v1 >> 30) & 0x3);
+ return;
+
+ case PDU_MD:
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ "%s MD pl=%u", dir, (v1 >> 30) & 0x3);
+ return;
+
+ case PDU_ERAK:
+ sscop->funcs->verbose(sscop, sscop->aarg,
+ "%s ERAK n(mr)=%u", dir, v1 & 0xffffff);
+ return;
+ }
+}
+#endif
+
+
+/*
+ * Initialize state of variables
+ */
+static void
+sscop_init(struct sscop *sscop)
+{
+ sscop->state = SSCOP_IDLE;
+
+ sscop->vt_sq = 0;
+ sscop->vr_sq = 0;
+ sscop->clear_buffers = 1;
+
+ sscop->ll_busy = 0;
+
+ sscop->rxq = 0;
+}
+
+static void
+sscop_clear(struct sscop *sscop)
+{
+ TIMER_STOP(sscop, cc);
+ TIMER_STOP(sscop, ka);
+ TIMER_STOP(sscop, nr);
+ TIMER_STOP(sscop, idle);
+ TIMER_STOP(sscop, poll);
+
+ FREE_UU(uu_bgn);
+ FREE_UU(uu_bgak);
+ FREE_UU(uu_bgrej);
+ FREE_UU(uu_end);
+ FREE_UU(uu_rs);
+
+ MSGQ_CLEAR(&sscop->xq);
+ MSGQ_CLEAR(&sscop->uxq);
+ MSGQ_CLEAR(&sscop->mxq);
+ MSGQ_CLEAR(&sscop->xbuf);
+ MSGQ_CLEAR(&sscop->rbuf);
+
+ SIGQ_CLEAR(&sscop->sigs);
+ SIGQ_CLEAR(&sscop->saved_sigs);
+}
+
+
+/*
+ * Allocate instance memory, initialize the state of all variables.
+ */
+struct sscop *
+sscop_create(void *a, const struct sscop_funcs *funcs)
+{
+ struct sscop *sscop;
+
+ MEMZALLOC(sscop, struct sscop *, sizeof(struct sscop));
+ if (sscop == NULL)
+ return (NULL);
+
+ if (a == NULL)
+ sscop->aarg = sscop;
+ else
+ sscop->aarg = a;
+ sscop->funcs = funcs;
+
+ sscop->maxk = MAXK;
+ sscop->maxj = MAXJ;
+ sscop->maxcc = MAXCC;
+ sscop->maxpd = MAXPD;
+ sscop->maxstat = MAXSTAT;
+ sscop->timercc = TIMERCC;
+ sscop->timerka = TIMERKA;
+ sscop->timernr = TIMERNR;
+ sscop->timerpoll = TIMERPOLL;
+ sscop->timeridle = TIMERIDLE;
+ sscop->robustness = 0;
+ sscop->poll_after_rex = 0;
+ sscop->mr = MAXMR;
+
+ TIMER_INIT(sscop, cc);
+ TIMER_INIT(sscop, nr);
+ TIMER_INIT(sscop, ka);
+ TIMER_INIT(sscop, poll);
+ TIMER_INIT(sscop, idle);
+
+ MSGQ_INIT(&sscop->xq);
+ MSGQ_INIT(&sscop->uxq);
+ MSGQ_INIT(&sscop->mxq);
+ MSGQ_INIT(&sscop->rbuf);
+ MSGQ_INIT(&sscop->xbuf);
+
+ SIGQ_INIT(&sscop->sigs);
+ SIGQ_INIT(&sscop->saved_sigs);
+
+ sscop_init(sscop);
+
+ return (sscop);
+}
+
+/*
+ * Free all resources in a sscop instance
+ */
+void
+sscop_destroy(struct sscop *sscop)
+{
+ sscop_reset(sscop);
+
+ MEMFREE(sscop);
+}
+
+/*
+ * Reset the SSCOP instance.
+ */
+void
+sscop_reset(struct sscop *sscop)
+{
+ sscop_clear(sscop);
+ sscop_init(sscop);
+}
+
+void
+sscop_getparam(const struct sscop *sscop, struct sscop_param *p)
+{
+ p->timer_cc = sscop->timercc;
+ p->timer_poll = sscop->timerpoll;
+ p->timer_keep_alive = sscop->timerka;
+ p->timer_no_response = sscop->timernr;
+ p->timer_idle = sscop->timeridle;
+ p->maxk = sscop->maxk;
+ p->maxj = sscop->maxj;
+ p->maxcc = sscop->maxcc;
+ p->maxpd = sscop->maxpd;
+ p->maxstat = sscop->maxstat;
+ p->mr = sscop->mr;
+ p->flags = 0;
+ if(sscop->robustness)
+ p->flags |= SSCOP_ROBUST;
+ if(sscop->poll_after_rex)
+ p->flags |= SSCOP_POLLREX;
+}
+
+int
+sscop_setparam(struct sscop *sscop, struct sscop_param *p, u_int *pmask)
+{
+ u_int mask = *pmask;
+
+ /* can change only in idle state */
+ if (sscop->state != SSCOP_IDLE)
+ return (EISCONN);
+
+ *pmask = 0;
+
+ /*
+ * first check all parameters
+ */
+ if ((mask & SSCOP_SET_TCC) && p->timer_cc == 0)
+ *pmask |= SSCOP_SET_TCC;
+ if ((mask & SSCOP_SET_TPOLL) && p->timer_poll == 0)
+ *pmask |= SSCOP_SET_TPOLL;
+ if ((mask & SSCOP_SET_TKA) && p->timer_keep_alive == 0)
+ *pmask |= SSCOP_SET_TKA;
+ if ((mask & SSCOP_SET_TNR) && p->timer_no_response == 0)
+ *pmask |= SSCOP_SET_TNR;
+ if ((mask & SSCOP_SET_TIDLE) && p->timer_idle == 0)
+ *pmask |= SSCOP_SET_TIDLE;
+ if ((mask & SSCOP_SET_MAXK) && p->maxk > MAXMAXK)
+ *pmask |= SSCOP_SET_MAXK;
+ if ((mask & SSCOP_SET_MAXJ) && p->maxj > MAXMAXJ)
+ *pmask |= SSCOP_SET_MAXJ;
+ if ((mask & SSCOP_SET_MAXCC) && p->maxcc > 255)
+ *pmask |= SSCOP_SET_MAXCC;
+ if ((mask & SSCOP_SET_MAXPD) && p->maxpd >= (1 << 24))
+ *pmask |= SSCOP_SET_MAXPD;
+ if ((mask & SSCOP_SET_MAXSTAT) &&
+ ((p->maxstat & 1) == 0 || p->maxstat == 1 || p->maxstat == 2 ||
+ p->maxstat * 4 > MAXMAXK - 8))
+ *pmask |= SSCOP_SET_MAXSTAT;
+ if ((mask & SSCOP_SET_MR) && p->mr >= (1 << 24) - 1)
+ *pmask |= SSCOP_SET_MR;
+
+ if (*pmask)
+ return (EINVAL);
+
+
+ /*
+ * now set it
+ */
+ if (mask & SSCOP_SET_TCC)
+ sscop->timercc = p->timer_cc;
+
+ if (mask & SSCOP_SET_TPOLL)
+ sscop->timerpoll = p->timer_poll;
+
+ if (mask & SSCOP_SET_TKA)
+ sscop->timerka = p->timer_keep_alive;
+
+ if (mask & SSCOP_SET_TNR)
+ sscop->timernr = p->timer_no_response;
+
+ if (mask & SSCOP_SET_TIDLE)
+ sscop->timeridle = p->timer_idle;
+
+ if (mask & SSCOP_SET_MAXK)
+ sscop->maxk = p->maxk;
+ if (mask & SSCOP_SET_MAXJ)
+ sscop->maxj = p->maxj;
+
+ if (mask & SSCOP_SET_MAXCC)
+ sscop->maxcc = p->maxcc;
+ if (mask & SSCOP_SET_MAXPD)
+ sscop->maxpd = p->maxpd;
+ if (mask & SSCOP_SET_MAXSTAT)
+ sscop->maxstat = p->maxstat;
+
+ if (mask & SSCOP_SET_MR)
+ sscop->mr = p->mr;
+
+ if (mask & SSCOP_SET_ROBUST)
+ sscop->robustness = ((p->flags & SSCOP_ROBUST) != 0);
+
+ if (mask & SSCOP_SET_POLLREX)
+ sscop->poll_after_rex = ((p->flags & SSCOP_POLLREX) != 0);
+
+ return (0);
+}
+
+enum sscop_state
+sscop_getstate(const struct sscop *sscop)
+{
+ return (sscop->state);
+}
+
+
+/************************************************************/
+/*
+ * EXTERNAL INPUT SIGNAL MAPPING
+ */
+
+/*
+ * Map AA signal to SSCOP internal signal
+ */
+int
+sscop_aasig(struct sscop *sscop, enum sscop_aasig sig,
+ struct SSCOP_MBUF_T *m, u_int arg)
+{
+ struct sscop_msg *msg;
+
+ if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) {
+ VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
+ "AA-Signal %u - bad signal", sig));
+ MBUF_FREE(m);
+ return (EINVAL);
+ }
+ VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
+ "AA-Signal %s in state %s with%s message",
+ sscop_sigs[sig], states[sscop->state], m ? "" : "out"));
+
+ MSG_ALLOC(msg);
+ if (msg == NULL) {
+ FAILURE("sscop: cannot allocate aasig");
+ MBUF_FREE(m);
+ return (ENOMEM);
+ }
+
+ switch(sig) {
+
+ case SSCOP_ESTABLISH_request:
+ msg->m = m;
+ msg->rexmit = arg;
+ sscop_signal(sscop, SIG_ESTAB_REQ, msg);
+ break;
+
+ case SSCOP_ESTABLISH_response:
+ msg->m = m;
+ msg->rexmit = arg;
+ sscop_signal(sscop, SIG_ESTAB_RESP, msg);
+ break;
+
+ case SSCOP_RELEASE_request:
+ msg->m = m;
+ sscop_signal(sscop, SIG_RELEASE_REQ, msg);
+ break;
+
+ case SSCOP_DATA_request:
+ msg->m = m;
+ sscop_signal(sscop, SIG_USER_DATA, msg);
+ break;
+
+ case SSCOP_UDATA_request:
+ msg->m = m;
+ sscop_signal(sscop, SIG_UDATA, msg);
+ break;
+
+ case SSCOP_RECOVER_response:
+ MBUF_FREE(m);
+ MSG_FREE(msg);
+ sscop_signal(sscop, SIG_RECOVER, NULL);
+ break;
+
+ case SSCOP_RESYNC_request:
+ msg->m = m;
+ sscop_signal(sscop, SIG_SYNC_REQ, msg);
+ break;
+
+ case SSCOP_RESYNC_response:
+ MBUF_FREE(m);
+ MSG_FREE(msg);
+ sscop_signal(sscop, SIG_SYNC_RESP, NULL);
+ break;
+
+ case SSCOP_RETRIEVE_request:
+ MBUF_FREE(m);
+ msg->rexmit = arg;
+ sscop_signal(sscop, SIG_RETRIEVE, msg);
+ break;
+
+ case SSCOP_ESTABLISH_indication:
+ case SSCOP_ESTABLISH_confirm:
+ case SSCOP_RELEASE_indication:
+ case SSCOP_RELEASE_confirm:
+ case SSCOP_DATA_indication:
+ case SSCOP_UDATA_indication:
+ case SSCOP_RECOVER_indication:
+ case SSCOP_RESYNC_indication:
+ case SSCOP_RESYNC_confirm:
+ case SSCOP_RETRIEVE_indication:
+ case SSCOP_RETRIEVE_COMPL_indication:
+ MBUF_FREE(m);
+ MSG_FREE(msg);
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Signal from layer management.
+ */
+int
+sscop_maasig(struct sscop *sscop, enum sscop_maasig sig, struct SSCOP_MBUF_T *m)
+{
+ struct sscop_msg *msg;
+
+ if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) {
+ VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
+ "MAA-Signal %u - bad signal", sig));
+ MBUF_FREE(m);
+ return (EINVAL);
+ }
+ VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
+ "MAA-Signal %s in state %s with%s message",
+ sscop_msigs[sig], states[sscop->state], m ? "" : "out"));
+
+ MSG_ALLOC(msg);
+ if (msg == NULL) {
+ FAILURE("sscop: cannot allocate maasig");
+ MBUF_FREE(m);
+ return (ENOMEM);
+ }
+
+ switch (sig) {
+
+ case SSCOP_MDATA_request:
+ msg->m = m;
+ sscop_signal(sscop, SIG_MDATA, msg);
+ break;
+
+ case SSCOP_MDATA_indication:
+ case SSCOP_MERROR_indication:
+ MBUF_FREE(m);
+ MSG_FREE(msg);
+ return (EINVAL);
+ }
+ return (0);
+}
+
+/*
+ * Map PDU to SSCOP signal.
+ */
+void
+sscop_input(struct sscop *sscop, struct SSCOP_MBUF_T *m)
+{
+ struct sscop_msg *msg;
+ union pdu pdu;
+ u_int size;
+
+ MSG_ALLOC(msg);
+ if(msg == NULL) {
+ FAILURE("sscop: cannot allocate in pdu msg");
+ MBUF_FREE(m);
+ return;
+ }
+
+ msg->m = m;
+ msg->rexmit = 0;
+
+ size = MBUF_LEN(m);
+
+ if(size % 4 != 0 || size < 4)
+ goto err;
+
+ pdu.sscop_null = MBUF_TRAIL32(m, -1);
+
+ VERBOSE(sscop, SSCOP_DBG_PDU, (sscop, sscop->aarg,
+ "got %s, size=%u", pdus[pdu.sscop_type], size));
+
+#ifdef SSCOP_DEBUG
+#define ENSURE(C,F) if(!(C)) { VERBOSE(sscop, SSCOP_DBG_PDU, F); goto err; }
+#else
+#define ENSURE(C,F) if(!(C)) goto err
+#endif
+
+#ifdef SSCOP_DEBUG
+ if (ISVERBOSE(sscop, SSCOP_DBG_PDU))
+ sscop_dump_pdu(sscop, "rx", m);
+#endif
+
+ switch(pdu.sscop_type) {
+
+ default:
+ ENSURE(0, (sscop, sscop->aarg,
+ "Bad PDU type %u", pdu.sscop_type));
+ break;
+
+ case PDU_BGN:
+ ENSURE(size >= 8U, (sscop, sscop->aarg,
+ "PDU_BGN size=%u", size));
+ ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
+ "PDU_BGN size=%u pl=%u", size, pdu.sscop_pl));
+ ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
+ "PDU_BGN size=%u", size));
+ sscop_signal(sscop, SIG_BGN, msg);
+ break;
+
+ case PDU_BGAK:
+ ENSURE(size >= 8U, (sscop, sscop->aarg,
+ "PDU_BGAK size=%u", size));
+ ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
+ "PDU_BGAK size=%u pl=%u", size, pdu.sscop_pl));
+ ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
+ "PDU_BGAK size=%u", size));
+ sscop_signal(sscop, SIG_BGAK, msg);
+ break;
+
+ case PDU_END:
+ ENSURE(size >= 8U, (sscop, sscop->aarg,
+ "PDU_END size=%u", size));
+ ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
+ "PDU_END size=%u pl=%u", size, pdu.sscop_pl));
+ ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
+ "PDU_END size=%u", size));
+ sscop_signal(sscop, SIG_END, msg);
+ break;
+
+ case PDU_ENDAK:
+ ENSURE(size == 8U, (sscop, sscop->aarg,
+ "PDU_ENDAK size=%u", size));
+ sscop_signal(sscop, SIG_ENDAK, msg);
+ break;
+
+ case PDU_BGREJ:
+ ENSURE(size >= 8U, (sscop, sscop->aarg,
+ "PDU_BGREJ size=%u", size));
+ ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
+ "PDU_BGREJ size=%u pl=%u", size, pdu.sscop_pl));
+ ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
+ "PDU_BGREJ size=%u", size));
+ sscop_signal(sscop, SIG_BGREJ, msg);
+ break;
+
+ case PDU_SD:
+ ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
+ "PDU_SD size=%u pl=%u", size, pdu.sscop_pl));
+ ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
+ "PDU_SD size=%u", size));
+ sscop_signal(sscop, SIG_SD, msg);
+ break;
+
+ case PDU_UD:
+ ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
+ "PDU_UD size=%u pl=%u", size, pdu.sscop_pl));
+ ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
+ "PDU_UD size=%u", size));
+ sscop_signal(sscop, SIG_UD, msg);
+ break;
+
+ case PDU_MD:
+ ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
+ "PDU_MD size=%u pl=%u", size, pdu.sscop_pl));
+ ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
+ "PDU_MD size=%u", size));
+ sscop_signal(sscop, SIG_MD, msg);
+ break;
+
+ case PDU_POLL:
+ ENSURE(size == 8U, (sscop, sscop->aarg,
+ "PDU_POLL size=%u", size));
+ sscop_signal(sscop, SIG_POLL, msg);
+ break;
+
+ case PDU_STAT:
+ ENSURE(size >= 12U, (sscop, sscop->aarg,
+ "PDU_STAT size=%u", size));
+ ENSURE(size <= 12U + 4 * sscop->maxstat, (sscop, sscop->aarg,
+ "PDU_STAT size=%u", size));
+ sscop_signal(sscop, SIG_STAT, msg);
+ break;
+
+ case PDU_RS:
+ ENSURE(size >= 8U, (sscop, sscop->aarg,
+ "PDU_RS size=%u", size));
+ ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
+ "PDU_RS size=%u pl=%u", size, pdu.sscop_pl));
+ ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
+ "PDU_RS size=%u", size));
+ sscop_signal(sscop, SIG_RS, msg);
+ break;
+
+ case PDU_RSAK:
+ ENSURE(size == 8U, (sscop, sscop->aarg,
+ "PDU_RSAK size=%u", size));
+ sscop_signal(sscop, SIG_RSAK, msg);
+ break;
+
+ case PDU_ER:
+ ENSURE(size == 8U, (sscop, sscop->aarg,
+ "PDU_ER size=%u", size));
+ sscop_signal(sscop, SIG_ER, msg);
+ break;
+
+ case PDU_ERAK:
+ ENSURE(size == 8U, (sscop, sscop->aarg,
+ "PDU_ERAK size=%u", size));
+ sscop_signal(sscop, SIG_ERAK, msg);
+ break;
+
+ case PDU_USTAT:
+ ENSURE(size == 16U, (sscop, sscop->aarg,
+ "PDU_ERAK size=%u", size));
+ sscop_signal(sscop, SIG_USTAT, msg);
+ break;
+ }
+#undef ENSURE
+ return;
+
+ err:
+ MAAL_ERROR(sscop, 'U', 0);
+ SSCOP_MSG_FREE(msg);
+}
+
+/************************************************************/
+/*
+ * UTILITIES
+ */
+
+/*
+ * Move the receiver window by N packets
+ */
+u_int
+sscop_window(struct sscop *sscop, u_int n)
+{
+ sscop->vr_mr += n;
+ return (SEQNO_DIFF(sscop->vr_mr, sscop->vr_r));
+}
+
+/*
+ * Lower layer busy handling
+ */
+u_int
+sscop_setbusy(struct sscop *sscop, int busy)
+{
+ u_int old = sscop->ll_busy;
+
+ if (busy > 0)
+ sscop->ll_busy = 1;
+ else if (busy == 0) {
+ sscop->ll_busy = 0;
+ if(old)
+ handle_sigs(sscop);
+ }
+
+ return (old);
+}
+
+const char *
+sscop_signame(enum sscop_aasig sig)
+{
+ static char str[40];
+
+ if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) {
+ sprintf(str, "BAD SSCOP_AASIG %u", sig);
+ return (str);
+ } else {
+ return (sscop_sigs[sig]);
+ }
+}
+
+const char *
+sscop_msigname(enum sscop_maasig sig)
+{
+ static char str[40];
+
+ if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) {
+ sprintf(str, "BAD SSCOP_MAASIG %u", sig);
+ return (str);
+ } else {
+ return (sscop_msigs[sig]);
+ }
+}
+
+const char *
+sscop_statename(enum sscop_state s)
+{
+ static char str[40];
+
+ if (s >= sizeof(states)/sizeof(states[0])) {
+ sprintf(str, "BAD SSCOP_STATE %u", s);
+ return (str);
+ } else {
+ return (states[s]);
+ }
+}
+
+
+/************************************************************/
+/*
+ * MACROS
+ */
+
+/*
+ * p 75: release buffers
+ */
+static void
+m_release_buffers(struct sscop *sscop)
+{
+ MSGQ_CLEAR(&sscop->xq);
+ MSGQ_CLEAR(&sscop->xbuf);
+ sscop->rxq = 0;
+ MSGQ_CLEAR(&sscop->rbuf);
+}
+
+/*
+ * P 75: Prepare retrival
+ */
+static void
+m_prepare_retrieval(struct sscop *sscop)
+{
+ struct sscop_msg *msg;
+
+ if (sscop->clear_buffers) {
+ MSGQ_CLEAR(&sscop->xq);
+ MSGQ_CLEAR(&sscop->xbuf);
+ }
+ MSGQ_FOREACH(msg, &sscop->xbuf)
+ msg->rexmit = 0;
+ sscop->rxq = 0;
+
+ MSGQ_CLEAR(&sscop->rbuf);
+}
+
+/*
+ * P 75: Prepare retrival
+ */
+static void
+m_prepare_recovery(struct sscop *sscop)
+{
+ struct sscop_msg *msg;
+
+ if(sscop->clear_buffers) {
+ MSGQ_CLEAR(&sscop->xq);
+ MSGQ_CLEAR(&sscop->xbuf);
+ }
+ MSGQ_FOREACH(msg, &sscop->xbuf)
+ msg->rexmit = 0;
+ sscop->rxq = 0;
+}
+
+
+/*
+ * P 75: Clear transmitter
+ */
+static void
+m_clear_transmitter(struct sscop *sscop)
+{
+ if(!sscop->clear_buffers) {
+ MSGQ_CLEAR(&sscop->xq);
+ MSGQ_CLEAR(&sscop->xbuf);
+ }
+}
+
+
+/*
+ * p 75: Deliver data
+ * Freeing the message is the responibility of the handler function.
+ */
+static void
+m_deliver_data(struct sscop *sscop)
+{
+ struct sscop_msg *msg;
+ u_int sn;
+
+ if ((msg = MSGQ_GET(&sscop->rbuf)) == NULL)
+ return;
+
+ if (sscop->clear_buffers) {
+ MSGQ_CLEAR(&sscop->rbuf);
+ return;
+ }
+
+ sn = msg->seqno + 1;
+ AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno);
+ MSG_FREE(msg);
+
+ while ((msg = MSGQ_GET(&sscop->rbuf)) != NULL) {
+ ASSERT(msg->seqno == sn);
+ if (++sn == SSCOP_MAXSEQNO)
+ sn = 0;
+ AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno);
+ MSG_FREE(msg);
+ }
+}
+
+/*
+ * P 75: Initialize state variables
+ */
+static void
+m_initialize_state(struct sscop *sscop)
+{
+ sscop->vt_s = 0;
+ sscop->vt_ps = 0;
+ sscop->vt_a = 0;
+
+ sscop->vt_pa = 1;
+ sscop->vt_pd = 0;
+ sscop->credit = 1;
+
+ sscop->vr_r = 0;
+ sscop->vr_h = 0;
+}
+
+/*
+ * p 76: Data retrieval
+ */
+static void
+m_data_retrieval(struct sscop *sscop, u_int rn)
+{
+ struct sscop_msg *s;
+
+ if (rn != SSCOP_RETRIEVE_UNKNOWN) {
+ if(rn >= SSCOP_RETRIEVE_TOTAL)
+ rn = sscop->vt_a;
+ else
+ rn++;
+ while(rn >= sscop->vt_a && rn < sscop->vt_s) {
+ if(rn == SSCOP_MAXSEQNO) rn = 0;
+ if((s = QFIND(&sscop->xbuf, rn)) != NULL) {
+ MSGQ_REMOVE(&sscop->xbuf, s);
+ AAL_DATA(sscop, SSCOP_RETRIEVE_indication,
+ s->m, 0);
+ MSG_FREE(s);
+ }
+ rn++;
+ }
+ }
+
+ while((s = MSGQ_GET(&sscop->xq)) != NULL) {
+ AAL_DATA(sscop, SSCOP_RETRIEVE_indication, s->m, 0);
+ MSG_FREE(s);
+ }
+ AAL_SIG(sscop, SSCOP_RETRIEVE_COMPL_indication);
+}
+
+/*
+ * P 76: Detect retransmission. PDU type must already be stripped.
+ */
+static int
+m_detect_retransmission(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union bgn bgn;
+
+ bgn.sscop_null = MBUF_TRAIL32(msg->m, -1);
+
+ if (sscop->vr_sq == bgn.sscop_bgns)
+ return (1);
+
+ sscop->vr_sq = bgn.sscop_bgns;
+ return (0);
+}
+
+/*
+ * P 76: Set POLL timer
+ */
+static void
+m_set_poll_timer(struct sscop *sscop)
+{
+ if(MSGQ_EMPTY(&sscop->xq) && sscop->vt_s == sscop->vt_a)
+ TIMER_RESTART(sscop, ka);
+ else
+ TIMER_RESTART(sscop, poll);
+}
+
+/*
+ * P 77: Reset data transfer timers
+ */
+static void
+m_reset_data_xfer_timers(struct sscop *sscop)
+{
+ TIMER_STOP(sscop, ka);
+ TIMER_STOP(sscop, nr);
+ TIMER_STOP(sscop, idle);
+ TIMER_STOP(sscop, poll);
+}
+
+/*
+ * P 77: Set data transfer timers
+ */
+static void
+m_set_data_xfer_timers(struct sscop *sscop)
+{
+ TIMER_RESTART(sscop, poll);
+ TIMER_RESTART(sscop, nr);
+}
+
+/*
+ * P 77: Initialize VR(MR)
+ */
+static void
+m_initialize_mr(struct sscop *sscop)
+{
+ sscop->vr_mr = sscop->mr;
+}
+
+/************************************************************/
+/*
+ * CONDITIONS
+ */
+static int
+c_ready_pduq(struct sscop *sscop)
+{
+ if (!sscop->ll_busy &&
+ (sscop->rxq != 0 ||
+ sscop->vt_s < sscop->vt_ms ||
+ TIMER_ISACT(sscop, idle)))
+ return (1);
+ return (0);
+}
+
+/************************************************************/
+/*
+ * SEND PDUS
+ */
+
+/*
+ * Send BG PDU.
+ */
+static void
+send_bgn(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
+{
+ union pdu pdu;
+ union bgn bgn;
+ struct SSCOP_MBUF_T *m;
+
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_BGN;
+ pdu.sscop_ns = sscop->vr_mr;
+
+ bgn.sscop_null = 0;
+ bgn.sscop_bgns = sscop->vt_sq;
+
+ if(uu) {
+ if ((m = MBUF_DUP(uu)) == NULL) {
+ FAILURE("sscop: cannot allocate BGN");
+ return;
+ }
+ pdu.sscop_pl += MBUF_PAD4(m);
+ } else {
+ if ((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate BGN");
+ return;
+ }
+ }
+
+ MBUF_APPEND32(m, bgn.sscop_null);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send BGREJ PDU.
+ */
+static void
+send_bgrej(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
+{
+ union pdu pdu;
+ union bgn bgn;
+ struct SSCOP_MBUF_T *m;
+
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_BGREJ;
+ bgn.sscop_null = 0;
+
+ if(uu) {
+ if((m = MBUF_DUP(uu)) == NULL) {
+ FAILURE("sscop: cannot allocate BGREJ");
+ return;
+ }
+ pdu.sscop_pl += MBUF_PAD4(m);
+ } else {
+ if((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate BGREJ");
+ return;
+ }
+ }
+
+ MBUF_APPEND32(m, bgn.sscop_null);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send BGAK PDU.
+ */
+static void
+send_bgak(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
+{
+ union pdu pdu;
+ union bgn bgn;
+ struct SSCOP_MBUF_T *m;
+
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_BGAK;
+ pdu.sscop_ns = sscop->vr_mr;
+ bgn.sscop_null = 0;
+
+ if(uu) {
+ if((m = MBUF_DUP(uu)) == NULL) {
+ FAILURE("sscop: cannot allocate BGAK");
+ return;
+ }
+ pdu.sscop_pl += MBUF_PAD4(m);
+ } else {
+ if((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate BGAK");
+ return;
+ }
+ }
+
+ MBUF_APPEND32(m, bgn.sscop_null);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send SD PDU. The function makes a duplicate of the message.
+ */
+static void
+send_sd(struct sscop *sscop, struct SSCOP_MBUF_T *m, u_int seqno)
+{
+ union pdu pdu;
+
+ if((m = MBUF_DUP(m)) == NULL) {
+ FAILURE("sscop: cannot allocate SD");
+ return;
+ }
+
+ pdu.sscop_null = 0;
+ pdu.sscop_pl = 0;
+ pdu.sscop_type = PDU_SD;
+ pdu.sscop_ns = seqno;
+
+ pdu.sscop_pl += MBUF_PAD4(m);
+
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send a UD PDU. The caller must free the sscop msg part.
+ */
+static void
+send_ud(struct sscop *sscop, struct SSCOP_MBUF_T *m)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_UD;
+
+ pdu.sscop_pl += MBUF_PAD4(m);
+
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send a MD PDU. The caller must free the sscop msg part.
+ */
+static void
+send_md(struct sscop *sscop, struct SSCOP_MBUF_T *m)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_MD;
+
+ pdu.sscop_pl += MBUF_PAD4(m);
+
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send END PDU.
+ */
+static void
+send_end(struct sscop *sscop, int src, struct SSCOP_MBUF_T *uu)
+{
+ union pdu pdu;
+ struct SSCOP_MBUF_T *m;
+
+ sscop->last_end_src = src;
+
+ pdu.sscop_null = 0;
+ pdu.sscop_s = src;
+ pdu.sscop_type = PDU_END;
+
+ if(uu) {
+ if((m = MBUF_DUP(uu)) == NULL) {
+ FAILURE("sscop: cannot allocate END");
+ return;
+ }
+ pdu.sscop_pl += MBUF_PAD4(m);
+ } else {
+ if((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate END");
+ return;
+ }
+ }
+
+ MBUF_APPEND32(m, 0);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send USTAT PDU. List must be terminated by -1.
+ */
+static void
+send_ustat(struct sscop *sscop, ...)
+{
+ va_list ap;
+ int f;
+ u_int n;
+ union pdu pdu;
+ union seqno seqno;
+ struct SSCOP_MBUF_T *m;
+
+ va_start(ap, sscop);
+ n = 0;
+ while((f = va_arg(ap, int)) >= 0)
+ n++;
+ va_end(ap);
+
+ if((m = MBUF_ALLOC(n * 4 + 8)) == NULL) {
+ FAILURE("sscop: cannot allocate USTAT");
+ return;
+ }
+
+ va_start(ap, sscop);
+ while((f = va_arg(ap, int)) >= 0) {
+ seqno.sscop_null = 0;
+ seqno.sscop_n = f;
+ MBUF_APPEND32(m, seqno.sscop_null);
+ }
+ va_end(ap);
+
+ seqno.sscop_null = 0;
+ seqno.sscop_n = sscop->vr_mr;
+ MBUF_APPEND32(m, seqno.sscop_null);
+
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_USTAT;
+ pdu.sscop_ns = sscop->vr_r;
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send ER PDU.
+ */
+static void
+send_er(struct sscop *sscop)
+{
+ union pdu pdu;
+ union bgn bgn;
+ struct SSCOP_MBUF_T *m;
+
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_ER;
+ pdu.sscop_ns = sscop->vr_mr;
+
+ bgn.sscop_null = 0;
+ bgn.sscop_bgns = sscop->vt_sq;
+
+ if((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate ER");
+ return;
+ }
+ MBUF_APPEND32(m, bgn.sscop_null);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send POLL PDU.
+ */
+static void
+send_poll(struct sscop *sscop)
+{
+ union pdu pdu;
+ union seqno seqno;
+ struct SSCOP_MBUF_T *m;
+
+ seqno.sscop_null = 0;
+ seqno.sscop_n = sscop->vt_ps;
+
+ pdu.sscop_null = 0;
+ pdu.sscop_ns = sscop->vt_s;
+ pdu.sscop_type = PDU_POLL;
+
+ if((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate POLL");
+ return;
+ }
+ MBUF_APPEND32(m, seqno.sscop_null);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send STAT PDU. List is already in buffer.
+ */
+static void
+send_stat(struct sscop *sscop, u_int nps, struct SSCOP_MBUF_T *m)
+{
+ union pdu pdu;
+ union seqno seqno;
+
+ seqno.sscop_null = 0;
+ seqno.sscop_n = nps;
+ MBUF_APPEND32(m, seqno.sscop_null);
+
+ seqno.sscop_null = 0;
+ seqno.sscop_n = sscop->vr_mr;
+ MBUF_APPEND32(m, seqno.sscop_null);
+
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_STAT;
+ pdu.sscop_ns = sscop->vr_r;
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send ENDAK PDU.
+ */
+static void
+send_endak(struct sscop *sscop)
+{
+ union pdu pdu;
+ union seqno seqno;
+ struct SSCOP_MBUF_T *m;
+
+ seqno.sscop_null = 0;
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_ENDAK;
+
+ if((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate ENDAK");
+ return;
+ }
+ MBUF_APPEND32(m, seqno.sscop_null);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send ERAK PDU.
+ */
+static void
+send_erak(struct sscop *sscop)
+{
+ union pdu pdu;
+ union seqno seqno;
+ struct SSCOP_MBUF_T *m;
+
+ seqno.sscop_null = 0;
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_ERAK;
+ pdu.sscop_ns = sscop->vr_mr;
+
+ if((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate ERAK");
+ return;
+ }
+ MBUF_APPEND32(m, seqno.sscop_null);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send RS PDU
+ */
+static void
+send_rs(struct sscop *sscop, int resend, struct SSCOP_MBUF_T *uu)
+{
+ union pdu pdu;
+ union bgn bgn;
+ struct SSCOP_MBUF_T *m;
+
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_RS;
+ pdu.sscop_ns = resend ? sscop->rs_mr : sscop->vr_mr;
+
+ bgn.sscop_null = 0;
+ bgn.sscop_bgns = resend ? sscop->rs_sq : sscop->vt_sq;
+
+ sscop->rs_mr = pdu.sscop_ns;
+ sscop->rs_sq = bgn.sscop_bgns;
+
+ if(uu) {
+ if((m = MBUF_DUP(uu)) == NULL) {
+ FAILURE("sscop: cannot allocate RS");
+ return;
+ }
+ pdu.sscop_pl += MBUF_PAD4(m);
+ } else {
+ if((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate RS");
+ return;
+ }
+ }
+
+ MBUF_APPEND32(m, bgn.sscop_null);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/*
+ * Send RSAK pdu
+ */
+static void
+send_rsak(struct sscop *sscop)
+{
+ union pdu pdu;
+ union seqno seqno;
+ struct SSCOP_MBUF_T *m;
+
+ seqno.sscop_null = 0;
+ pdu.sscop_null = 0;
+ pdu.sscop_type = PDU_RSAK;
+ pdu.sscop_ns = sscop->vr_mr;
+
+ if((m = MBUF_ALLOC(8)) == NULL) {
+ FAILURE("sscop: cannot allocate RSAK");
+ return;
+ }
+
+ MBUF_APPEND32(m, seqno.sscop_null);
+ MBUF_APPEND32(m, pdu.sscop_null);
+
+ AAL_SEND(sscop, m);
+}
+
+/************************************************************/
+/*
+ * P 31; IDLE && AA-ESTABLISH-request
+ * arg is UU data (opt).
+ */
+static void
+sscop_idle_establish_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ u_int br = uu->rexmit;
+
+ SET_UU(uu_bgn, uu);
+
+ m_clear_transmitter(sscop);
+
+ sscop->clear_buffers = br;
+
+ sscop->vt_cc = 1;
+ sscop->vt_sq++;
+
+ m_initialize_mr(sscop);
+
+ send_bgn(sscop, sscop->uu_bgn);
+
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_PEND);
+}
+
+/*
+ * P 31: IDLE && BGN PDU
+ * arg is the received PDU (freed).
+ */
+static void
+sscop_idle_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+ union bgn bgn;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(sscop->robustness) {
+ bgn.sscop_null = MBUF_STRIP32(msg->m);
+ sscop->vr_sq = bgn.sscop_bgns;
+ } else {
+ if(m_detect_retransmission(sscop, msg)) {
+ send_bgrej(sscop, sscop->uu_bgrej);
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+ }
+
+ sscop->vt_ms = pdu.sscop_ns;
+ sscop_set_state(sscop, SSCOP_IN_PEND);
+
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
+}
+
+/*
+ * p 31: IDLE && ENDAK PDU
+ * p 34: OUT_PEND && ENDAK PDU
+ * p 34: OUT_PEND && SD PDU
+ * p 34: OUT_PEND && ERAK PDU
+ * p 34: OUT_PEND && END PDU
+ * p 34: OUT_PEND && STAT PDU
+ * p 34: OUT_PEND && USTAT PDU
+ * p 34: OUT_PEND && POLL PDU
+ * p 36: OUT_PEND && RS PDU
+ * p 36: OUT_PEND && RSAK PDU
+ * p 40: OUTGOING_DISCONNECT_PENDING && SD PDU
+ * p 40: OUTGOING_DISCONNECT_PENDING && BGAK PDU
+ * p 40: OUTGOING_DISCONNECT_PENDING && POLL PDU
+ * p 40: OUTGOING_DISCONNECT_PENDING && STAT PDU
+ * p 40: OUTGOING_DISCONNECT_PENDING && USTAT PDU
+ * p 41: OUTGOING_DISCONNECT_PENDING && ERAK PDU
+ * p 42: OUTGOING_DISCONNECT_PENDING && ER PDU
+ * p 42: OUTGOING_DISCONNECT_PENDING && RS PDU
+ * p 42: OUTGOING_DISCONNECT_PENDING && RSAK PDU
+ * p 43: OUTGOING_RESYNC && ER PDU
+ * p 43: OUTGOING_RESYNC && POLL PDU
+ * p 44: OUTGOING_RESYNC && STAT PDU
+ * p 44: OUTGOING_RESYNC && USTAT PDU
+ * p 45: OUTGOING_RESYNC && BGAK PDU
+ * p 45: OUTGOING_RESYNC && SD PDU
+ * p 45: OUTGOING_RESYNC && ERAK PDU
+ * P 60: READY && BGAK PDU
+ * P 60: READY && ERAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_ignore_pdu(struct sscop *sscop __unused, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 31: IDLE && END PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_end(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ send_endak(sscop);
+}
+
+/*
+ * p 31: IDLE && ER PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_er(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'L', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+}
+
+/*
+ * p 31: IDLE && BGREJ PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_bgrej(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'D', 0);
+ FREE_UU(uu_end);
+}
+
+/*
+ * p 32: IDLE && POLL PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_poll(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'G', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+}
+
+/*
+ * p 32: IDLE && SD PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_sd(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'A', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+}
+
+/*
+ * p 32: IDLE && BGAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_bgak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'C', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+}
+
+/*
+ * p 32: IDLE && ERAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_erak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'M', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+}
+
+/*
+ * p 32: IDLE && STAT PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_stat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'H', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+}
+
+/*
+ * p 32: IDLE && USTAT PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_ustat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'I', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+}
+
+/*
+ * p 33: IDLE & RS PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_rs(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'J', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+}
+
+/*
+ * p 33: IDLE & RSAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_idle_rsak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'K', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+}
+
+/*
+ * p 33: IDLE && PDU_Q
+ * p XX: OUTPEND && PDU_Q
+ * p 39: IN_PEND && PDU_Q
+ * p 45: OUT_RESYNC_PEND && PDU_Q
+ * p 48: IN_RESYNC_PEND && PDU_Q
+ * no arg
+ */
+static void
+sscop_flush_pduq(struct sscop *sscop __unused, struct sscop_msg *unused __unused)
+{
+#if 0
+ MSGQ_CLEAR(&sscop->xq);
+#endif
+}
+
+/*
+ * p 34: OUT_PEND && BGAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outpend_bgak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_ms = pdu.sscop_ns;
+
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0);
+
+ m_initialize_state(sscop);
+ m_set_data_xfer_timers(sscop);
+
+ sscop_set_state(sscop, SSCOP_READY);
+}
+
+/*
+ * P 34: OUT_PEND && BGREJ PDU
+ */
+static void
+sscop_outpend_bgrej(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl, 0);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * P 35: OUT_PEND && TIMER_CC expiry
+ * no arg
+ */
+static void
+sscop_outpend_tcc(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ if(sscop->vt_cc >= sscop->maxcc) {
+ MAAL_ERROR(sscop, 'O', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+ } else {
+ sscop->vt_cc++;
+ send_bgn(sscop, sscop->uu_bgn);
+ TIMER_RESTART(sscop, cc);
+ }
+}
+
+/*
+ * P 35: OUT_PEND && RELEASE_REQ
+ * arg is UU
+ */
+static void
+sscop_outpend_release_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_end, uu);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_cc = 1;
+ send_end(sscop, 0, sscop->uu_end);
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
+}
+
+/*
+ * P 36: OUT_PEND && BGN PDU
+ * arg is the received PDU (freed).
+ */
+static void
+sscop_outpend_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+
+ sscop->vt_ms = pdu.sscop_ns;
+
+ m_initialize_mr(sscop);
+
+ send_bgak(sscop, sscop->uu_bgak);
+
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0);
+
+ m_initialize_state(sscop);
+
+ m_set_data_xfer_timers(sscop);
+
+ sscop_set_state(sscop, SSCOP_READY);
+}
+
+/*
+ * p 37: IN_PEND && AA-ESTABLISH.response
+ * arg is UU
+ */
+static void
+sscop_inpend_establish_resp(struct sscop *sscop, struct sscop_msg *uu)
+{
+ u_int br = uu->rexmit;
+
+ SET_UU(uu_bgak, uu);
+
+ m_clear_transmitter(sscop);
+ sscop->clear_buffers = br;
+ m_initialize_mr(sscop);
+ send_bgak(sscop, sscop->uu_bgak);
+ m_initialize_state(sscop);
+ m_set_data_xfer_timers(sscop);
+
+ sscop_set_state(sscop, SSCOP_READY);
+}
+
+/*
+ * p 37: IN_PEND && AA-RELEASE.request
+ * arg is uu.
+ */
+static void
+sscop_inpend_release_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_bgrej, uu);
+
+ send_bgrej(sscop, sscop->uu_bgrej);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 37: IN_PEND && BGN PDU
+ * arg is pdu. (freed)
+ */
+static void
+sscop_inpend_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ sscop->vt_ms = pdu.sscop_ns;
+
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
+}
+
+/*
+ * p 37: IN_PEND && ER PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_er(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'L', 0);
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 37: IN_PEND && ENDAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_endak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'F', 0);
+
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 38: IN_PEND && BGAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_bgak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'C', 0);
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 38: IN_PEND && BGREJ PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_bgrej(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'D', 0);
+
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+
+ SSCOP_MSG_FREE(msg);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 38: IN_PEND && SD PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_sd(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'A', 0);
+
+ SSCOP_MSG_FREE(msg);
+
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 38: IN_PEND && USTAT PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_ustat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'I', 0);
+
+ SSCOP_MSG_FREE(msg);
+
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 38: IN_PEND && STAT PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_stat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'H', 0);
+
+ SSCOP_MSG_FREE(msg);
+
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 38: IN_PEND && POLL PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_poll(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'G', 0);
+
+ SSCOP_MSG_FREE(msg);
+
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 39: IN_PEND && ERAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_erak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'M', 0);
+}
+
+/*
+ * p 39: IN_PEND & RS PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_rs(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'J', 0);
+}
+
+/*
+ * p 39: IN_PEND & RSAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inpend_rsak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'K', 0);
+}
+
+/*
+ * p 39: IN_PEND && END PDU
+ * arg is pdu (freed).
+ * no uui
+ */
+static void
+sscop_inpend_end(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ send_endak(sscop);
+
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
+ msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 40: OUT_DIS_PEND && SSCOP_ESTABLISH_request
+ * no arg.
+ * no uui.
+ */
+static void
+sscop_outdis_establish_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_bgn, uu);
+
+ TIMER_STOP(sscop, cc);
+ m_clear_transmitter(sscop);
+ sscop->clear_buffers = 1;
+ sscop->vt_cc = 1;
+ sscop->vt_sq++;
+ m_initialize_mr(sscop);
+ send_bgn(sscop, sscop->uu_bgn);
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_PEND);
+}
+
+/*
+ * p 41: OUT_DIS_PEND && END PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outdis_end(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ send_endak(sscop);
+
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 41: OUT_DIS_PEND && ENDAK PDU
+ * p 41: OUT_DIS_PEND && BGREJ PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_outdis_endak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 41: OUT_DIS_PEND && TIMER CC expiry
+ * no arg
+ */
+static void
+sscop_outdis_cc(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ if(sscop->vt_cc >= sscop->maxcc) {
+ MAAL_ERROR(sscop, 'O', 0);
+ AAL_SIG(sscop, SSCOP_RELEASE_confirm);
+ sscop_set_state(sscop, SSCOP_IDLE);
+ } else {
+ sscop->vt_cc++;
+ send_end(sscop, sscop->last_end_src, sscop->uu_end);
+ TIMER_RESTART(sscop, cc);
+ }
+}
+
+/*
+ * p 42: OUT_DIS_PEND && BGN PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outdis_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ FREE_UU(uu_bgak);
+ send_bgak(sscop, NULL);
+ send_end(sscop, sscop->last_end_src, sscop->uu_end);
+ SSCOP_MSG_FREE(msg);
+
+ } else {
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_SIG(sscop, SSCOP_RELEASE_confirm);
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
+ msg, pdu.sscop_pl, 0);
+ sscop_set_state(sscop, SSCOP_IN_PEND);
+ }
+}
+
+/*
+ * p 43: OUT_RESYNC_PEND && BGN PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outsync_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ send_bgak(sscop, sscop->uu_bgak);
+ send_rs(sscop, 1, sscop->uu_rs);
+ SSCOP_MSG_FREE(msg);
+ } else {
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
+ msg, pdu.sscop_pl, 0);
+ sscop_set_state(sscop, SSCOP_IN_PEND);
+ }
+}
+
+/*
+ * p 43: OUT_RESYNC_PEND && ENDAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outsync_endak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ TIMER_STOP(sscop, cc);
+ MAAL_ERROR(sscop, 'F', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 43: OUT_RESYNC_PEND && BGREJ PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outsync_bgrej(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ TIMER_STOP(sscop, cc);
+ MAAL_ERROR(sscop, 'D', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 43: OUT_RESYNC_PEND && END PDU
+ * arg is pdu (freed).
+ * no UU-data
+ */
+static void
+sscop_outsync_end(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ send_endak(sscop);
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl,
+ (u_int)pdu.sscop_s);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 44: OUT_RESYNC && TIMER CC expiry
+ */
+static void
+sscop_outsync_cc(struct sscop *sscop, struct sscop_msg *msg __unused)
+{
+ if(sscop->vt_cc == sscop->maxcc) {
+ MAAL_ERROR(sscop, 'O', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+ } else {
+ sscop->vt_cc++;
+ send_rs(sscop, 1, sscop->uu_rs);
+ TIMER_RESTART(sscop, cc);
+ }
+}
+
+/*
+ * p 44: OUT_RESYNC && AA-RELEASE.request
+ * arg is UU
+ */
+static void
+sscop_outsync_release_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_end, uu);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_cc = 1;
+ send_end(sscop, 0, sscop->uu_end);
+ TIMER_RESTART(sscop, cc);
+ sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
+}
+
+/*
+ * p 45: OUT_RESYNC && RS PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outsync_rs(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_ms = pdu.sscop_ns;
+ m_initialize_mr(sscop);
+ send_rsak(sscop);
+ AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_confirm, msg, pdu.sscop_pl, 0);
+ m_initialize_state(sscop);
+ m_set_data_xfer_timers(sscop);
+ sscop_set_state(sscop, SSCOP_READY);
+}
+
+/*
+ * p 45: OUT_RESYNC && RSAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outsync_rsak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ SSCOP_MSG_FREE(msg);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_SIG(sscop, SSCOP_RESYNC_confirm);
+ m_initialize_state(sscop);
+ m_set_data_xfer_timers(sscop);
+ sscop_set_state(sscop, SSCOP_READY);
+}
+
+/*
+ * p 46: IN_RESYNC_PEND && AA-RESYNC.response
+ */
+static void
+sscop_insync_sync_resp(struct sscop *sscop, struct sscop_msg *noarg __unused)
+{
+ m_initialize_mr(sscop);
+ send_rsak(sscop);
+ m_clear_transmitter(sscop);
+ m_initialize_state(sscop);
+ m_set_data_xfer_timers(sscop);
+ sscop_set_state(sscop, SSCOP_READY);
+}
+
+/*
+ * p 46: IN_RESYNC_PEND && AA-RELEASE.request
+ * arg is uu
+ */
+static void
+sscop_insync_release_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_end, uu);
+
+ sscop->vt_cc = 1;
+ send_end(sscop, 0, sscop->uu_end);
+ TIMER_RESTART(sscop, cc);
+ sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
+}
+
+/*
+ * p 46: IN_RESYNC_PEND && ENDAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_endak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'F', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 46: IN_RESYNC_PEND && BGREJ PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_bgrej(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'D', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 46: IN_RESYNC_PEND && END PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_end(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ send_endak(sscop);
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
+ msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 47: IN_RESYNC_PEND && ER PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_er(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'L', 0);
+}
+
+/*
+ * p 47: IN_RESYNC_PEND && BGN PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ MAAL_ERROR(sscop, 'B', 0);
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
+
+ sscop_set_state(sscop, SSCOP_IN_PEND);
+}
+
+/*
+ * p 47: IN_RESYNC_PEND && SD PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_sd(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'A', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 47: IN_RESYNC_PEND && POLL PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_poll(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'G', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 47: IN_RESYNC_PEND && STAT PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_stat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'H', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 47: IN_RESYNC_PEND && USTAT PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_ustat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'I', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 48: IN_RESYNC_PEND && BGAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_bgak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'C', 0);
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 48: IN_RESYNC_PEND && ERAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_erak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'M', 0);
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 48: IN_RESYNC_PEND && RS PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_rs(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'J', 0);
+}
+
+/*
+ * p 48: IN_RESYNC_PEND && RSAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_insync_rsak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'K', 0);
+ SSCOP_MSG_FREE(msg);
+}
+
+
+/*
+ * p 49: OUT_REC_PEND && AA-DATA.request
+ * arg is message (queued).
+ */
+static void
+sscop_outrec_userdata(struct sscop *sscop, struct sscop_msg *msg)
+{
+ if(!sscop->clear_buffers) {
+ MSGQ_APPEND(&sscop->xq, msg);
+ sscop_signal(sscop, SIG_PDU_Q, msg);
+ } else {
+ SSCOP_MSG_FREE(msg);
+ }
+}
+
+/*
+ * p 49: OUT_REC_PEND && BGAK PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_outrec_bgak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'C', 0);
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 49: OUT_REC_PEND && ERAK PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_outrec_erak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_ms = pdu.sscop_ns;
+ m_deliver_data(sscop);
+
+ AAL_SIG(sscop, SSCOP_RECOVER_indication);
+
+ sscop_set_state(sscop, SSCOP_REC_PEND);
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 49: OUT_REC_PEND && END PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_outrec_end(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ send_endak(sscop);
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
+ msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
+
+ MSGQ_CLEAR(&sscop->rbuf);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 49: OUT_REC_PEND && ENDAK PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_outrec_endak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'F', 0);
+ TIMER_STOP(sscop, cc);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ MSGQ_CLEAR(&sscop->rbuf);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 49: OUT_REC_PEND && BGREJ PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_outrec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'D', 0);
+ TIMER_STOP(sscop, cc);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ MSGQ_CLEAR(&sscop->rbuf);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 50: OUT_REC_PEND && TIMER CC expiry
+ * no arg.
+ */
+static void
+sscop_outrec_cc(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ if(sscop->vt_cc >= sscop->maxcc) {
+ MAAL_ERROR(sscop, 'O', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ MSGQ_CLEAR(&sscop->rbuf);
+ sscop_set_state(sscop, SSCOP_IDLE);
+ } else {
+ sscop->vt_cc++;
+ send_er(sscop);
+ TIMER_RESTART(sscop, cc);
+ }
+}
+
+/*
+ * p 50: OUT_REC_PEND && SSCOP_RELEASE_request
+ * arg is UU
+ */
+static void
+sscop_outrec_release_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_end, uu);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_cc = 1;
+ send_end(sscop, 0, sscop->uu_end);
+ MSGQ_CLEAR(&sscop->rbuf);
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
+}
+
+/*
+ * p 51: OUT_REC_PEND && AA-RESYNC.request
+ * arg is uu
+ */
+static void
+sscop_outrec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_rs, uu);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_cc = 1;
+ sscop->vt_sq++;
+ m_initialize_mr(sscop);
+ send_rs(sscop, 0, sscop->uu_rs);
+ m_clear_transmitter(sscop);
+ MSGQ_CLEAR(&sscop->rbuf);
+ TIMER_RESTART(sscop, cc);
+}
+
+/*
+ * p 51: OUT_REC_PEND && BGN PDU
+ * arg is pdu (freed).
+ * no uui
+ */
+static void
+sscop_outrec_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ MAAL_ERROR(sscop, 'B', 0);
+ SSCOP_MSG_FREE(msg);
+ } else {
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
+ msg, pdu.sscop_pl, 0);
+ MSGQ_CLEAR(&sscop->rbuf);
+
+ sscop_set_state(sscop, SSCOP_IN_PEND);
+ }
+}
+
+/*
+ * p 51: OUT_REC_PEND && ER PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outrec_er(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ MAAL_ERROR(sscop, 'L', 0);
+ } else {
+ TIMER_STOP(sscop, cc);
+ sscop->vt_ms = pdu.sscop_ns;
+ m_initialize_mr(sscop);
+ send_erak(sscop);
+ m_deliver_data(sscop);
+
+ AAL_SIG(sscop, SSCOP_RECOVER_indication);
+
+ sscop_set_state(sscop, SSCOP_REC_PEND);
+ }
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 52: OUT_REC_PEND && SD PDU queued
+ * no arg.
+ */
+static void
+sscop_outrec_pduq(struct sscop *sscop, struct sscop_msg *msg)
+{
+ sscop_save_signal(sscop, SIG_PDU_Q, msg);
+}
+
+/*
+ * p 52: OUT_REC_PEND && RSAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outrec_rsak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'K', 0);
+}
+
+/*
+ * p 52: OUT_REC_PEND && RS PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_outrec_rs(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'J', 0);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ TIMER_STOP(sscop, cc);
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
+ MSGQ_CLEAR(&sscop->rbuf);
+ sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
+}
+
+/*
+ * p 53: REC_PEND && BGAK PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_rec_bgak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'C', 0);
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 53: REC_PEND && END PDU
+ * arg is pdu (freed)
+ * no uui
+ */
+static void
+sscop_rec_end(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ send_endak(sscop);
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
+ msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 53: REC_PEND && ENDAK PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_rec_endak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'F', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 53: REC_PEND && BGREJ PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_rec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'D', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 54: REC_PEND && RELEASE
+ * arg is UU
+ */
+static void
+sscop_rec_release_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_end, uu);
+
+ sscop->vt_cc = 1;
+ send_end(sscop, 0, sscop->uu_end);
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
+}
+
+/*
+ * p 54: REC_PEND && RSAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_rec_rsak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'K', 0);
+ SSCOP_MSG_FREE(msg);
+}
+
+
+/*
+ * p 54: REC_PEND && RS PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_rec_rs(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'J', 0);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
+
+ sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
+}
+
+/*
+ * p 54: REC_PEND && RECOVER response
+ * no arg
+ */
+static void
+sscop_rec_recover(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ if(!sscop->clear_buffers) {
+ MSGQ_CLEAR(&sscop->xbuf);
+ }
+ m_initialize_state(sscop);
+ m_set_data_xfer_timers(sscop);
+
+ sscop_set_state(sscop, SSCOP_READY);
+}
+
+/*
+ * p 54: REC_PEND && RESYNC request
+ * arg is uu
+ */
+static void
+sscop_rec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_rs, uu);
+
+ m_clear_transmitter(sscop);
+ sscop->vt_cc = 1;
+ sscop->vt_sq++;
+ m_initialize_mr(sscop);
+ send_rs(sscop, 0, sscop->uu_rs);
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
+}
+
+/*
+ * p 55: REC_PEND && SD PDU queued
+ * no arg
+ */
+static void
+sscop_rec_pduq(struct sscop *sscop, struct sscop_msg *msg)
+{
+ sscop_save_signal(sscop, SIG_PDU_Q, msg);
+}
+
+/*
+ * p 55: REC_PEND && ER PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_rec_er(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ send_erak(sscop);
+ } else {
+ MAAL_ERROR(sscop, 'L', 0);
+ }
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 55: REC_PEND && BGN PDU
+ * arg is pdu (freed)
+ * no uui
+ */
+static void
+sscop_rec_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ MAAL_ERROR(sscop, 'B', 0);
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
+
+ sscop_set_state(sscop, SSCOP_IN_PEND);
+}
+
+/*
+ * p 55: REC_PEND && STAT PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_rec_stat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'H', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 55: REC_PEND && USTAT PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_rec_ustat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'I', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ sscop_set_state(sscop, SSCOP_IDLE);
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 56: IN_REC_PEND && AA-RECOVER.response
+ * no arg
+ */
+static void
+sscop_inrec_recover(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ if(!sscop->clear_buffers) {
+ MSGQ_CLEAR(&sscop->xbuf);
+ }
+ m_initialize_mr(sscop);
+ send_erak(sscop);
+ m_initialize_state(sscop);
+ m_set_data_xfer_timers(sscop);
+
+ sscop_set_state(sscop, SSCOP_READY);
+}
+
+/*
+ * p 56: IN_REC_PEND && SD PDU queued
+ * no arg
+ */
+static void
+sscop_inrec_pduq(struct sscop *sscop, struct sscop_msg *msg)
+{
+ sscop_save_signal(sscop, SIG_PDU_Q, msg);
+}
+
+/*
+ * p 56: IN_REC_PEND && AA-RELEASE.request
+ * arg is UU
+ */
+static void
+sscop_inrec_release_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_end, uu);
+
+ sscop->vt_cc = 1;
+ send_end(sscop, 0, sscop->uu_end);
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
+}
+
+/*
+ * p 56: IN_REC_PEND && END PDU
+ * arg is pdu (freed).
+ * no uui
+ */
+static void
+sscop_inrec_end(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ send_endak(sscop);
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
+ msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 56: IN_REC_PEND && RESYNC_REQ
+ */
+static void
+sscop_inrec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_rs, uu);
+
+ m_clear_transmitter(sscop);
+ sscop->vt_cc = 1;
+ sscop->vt_sq++;
+ m_initialize_mr(sscop);
+ send_rs(sscop, 0, sscop->uu_rs);
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
+}
+
+
+/*
+ * p 57: IN_REC_PEND && ENDAK PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_inrec_endak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'F', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ SSCOP_MSG_FREE(msg);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 57: IN_REC_PEND && BGREJ PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_inrec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'D', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ SSCOP_MSG_FREE(msg);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 57: IN_REC_PEND && USTAT PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_inrec_ustat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'I', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ SSCOP_MSG_FREE(msg);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 57: IN_REC_PEND && STAT PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_inrec_stat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'H', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ SSCOP_MSG_FREE(msg);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 57: IN_REC_PEND && POLL PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_inrec_poll(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'G', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ SSCOP_MSG_FREE(msg);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 57: IN_REC_PEND && SD PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_inrec_sd(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'A', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ SSCOP_MSG_FREE(msg);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 58: IN_REC_PEND && RSAK PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inrec_rsak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'K', 0);
+}
+
+/*
+ * p 58: IN_REC_PEND && RS PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_inrec_rs(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ SSCOP_MSG_FREE(msg);
+ MAAL_ERROR(sscop, 'J', 0);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
+
+ sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
+}
+
+/*
+ * p 59: IN_REC_PEND && ER PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_inrec_er(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(!m_detect_retransmission(sscop, msg)) {
+ MAAL_ERROR(sscop, 'L', 0);
+ }
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 59: IN_REC_PEND && BGN PDU
+ * arg is pdu (freed).
+ * no uui
+ */
+static void
+sscop_inrec_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ MAAL_ERROR(sscop, 'B', 0);
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
+
+ sscop_set_state(sscop, SSCOP_IN_PEND);
+}
+
+/*
+ * p 59: IN_REC_PEND && BGAK PDU
+ * arg is pdu (freed)
+ * no uui
+ */
+static void
+sscop_inrec_bgak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'C', 0);
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 59: IN_REC_PEND && ERAK PDU
+ * arg is pdu (freed)
+ * no uui
+ */
+static void
+sscop_inrec_erak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MAAL_ERROR(sscop, 'M', 0);
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 60: READY && RESYNC request
+ * arg is UU
+ */
+static void
+sscop_ready_sync_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_rs, uu);
+
+ m_reset_data_xfer_timers(sscop);
+ sscop->vt_cc = 1;
+ sscop->vt_sq++;
+ m_initialize_mr(sscop);
+ send_rs(sscop, 0, sscop->uu_rs);
+ m_release_buffers(sscop);
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
+}
+
+
+/*
+ * p 60: READY && AA-RELEASE.request
+ * arg is uu.
+ */
+static void
+sscop_ready_release_req(struct sscop *sscop, struct sscop_msg *uu)
+{
+ SET_UU(uu_end, uu);
+
+ m_reset_data_xfer_timers(sscop);
+ sscop->vt_cc = 1;
+ send_end(sscop, 0, sscop->uu_end);
+ m_prepare_retrieval(sscop);
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
+}
+
+/*
+ * p 61: READY && ER PDU
+ * arg is pdu (freed).
+ */
+static void
+sscop_ready_er(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ TIMER_RESTART(sscop, nr);
+ send_erak(sscop);
+ } else {
+ m_reset_data_xfer_timers(sscop);
+ sscop->vt_ms = pdu.sscop_ns;
+ m_prepare_recovery(sscop);
+ m_deliver_data(sscop);
+
+ AAL_SIG(sscop, SSCOP_RECOVER_indication);
+
+ sscop_set_state(sscop, SSCOP_IN_REC_PEND);
+ }
+
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 61: READY && BGN PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_ready_bgn(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ TIMER_RESTART(sscop, nr);
+ send_bgak(sscop, sscop->uu_bgak);
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ m_reset_data_xfer_timers(sscop);
+ sscop->vt_ms = pdu.sscop_ns;
+
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
+ AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
+
+ m_prepare_retrieval(sscop);
+
+ sscop_set_state(sscop, SSCOP_IN_PEND);
+}
+
+/*
+ * p 62: READY && ENDAK PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_ready_endak(struct sscop *sscop, struct sscop_msg *msg)
+{
+ m_reset_data_xfer_timers(sscop);
+ MAAL_ERROR(sscop, 'F', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ m_prepare_retrieval(sscop);
+ SSCOP_MSG_FREE(msg);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 62: READY && BGREJ PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_ready_bgrej(struct sscop *sscop, struct sscop_msg *msg)
+{
+ m_reset_data_xfer_timers(sscop);
+ MAAL_ERROR(sscop, 'D', 0);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ m_prepare_retrieval(sscop);
+ SSCOP_MSG_FREE(msg);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 62: READY && RS PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_ready_rs(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ if(m_detect_retransmission(sscop, msg)) {
+ SSCOP_MSG_FREE(msg);
+ TIMER_RESTART(sscop, nr);
+ send_rsak(sscop);
+ return;
+ }
+ (void)MBUF_STRIP32(msg->m);
+
+ m_reset_data_xfer_timers(sscop);
+ sscop->vt_ms = pdu.sscop_ns;
+ AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
+ m_prepare_retrieval(sscop);
+
+ sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
+}
+
+/*
+ * p 62: READY && END PDU
+ * arg is pdu (freed)
+ */
+static void
+sscop_ready_end(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ (void)MBUF_STRIP32(msg->m);
+
+ m_reset_data_xfer_timers(sscop);
+ send_endak(sscop);
+ AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
+ msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
+ m_prepare_retrieval(sscop);
+
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 63: READY && POLL expiry
+ */
+static void
+sscop_ready_tpoll(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ sscop->vt_ps++;
+ send_poll(sscop);
+ sscop->vt_pd = 0;
+ m_set_poll_timer(sscop);
+}
+
+/*
+ * p 63: READY && KEEP_ALIVE expiry
+ */
+static void
+sscop_ready_tka(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ sscop->vt_ps++;
+ send_poll(sscop);
+ sscop->vt_pd = 0;
+ m_set_poll_timer(sscop);
+}
+
+/*
+ * p 63: READY && IDLE expiry
+ */
+static void
+sscop_ready_tidle(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ TIMER_RESTART(sscop, nr);
+ sscop->vt_ps++;
+ send_poll(sscop);
+ sscop->vt_pd = 0;
+ m_set_poll_timer(sscop);
+}
+
+/*
+ * p 63: READY && NO_RESPONSE expiry
+ * no arg
+ */
+static void
+sscop_ready_nr(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ m_reset_data_xfer_timers(sscop);
+ MAAL_ERROR(sscop, 'P', 0);
+ FREE_UU(uu_end);
+ send_end(sscop, 1, NULL);
+ AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
+ m_prepare_retrieval(sscop);
+ sscop_set_state(sscop, SSCOP_IDLE);
+}
+
+/*
+ * p 63: READY && AA-DATA.request
+ * arg is message (queued).
+ */
+static void
+sscop_ready_userdata(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MSGQ_APPEND(&sscop->xq, msg);
+
+ sscop_signal(sscop, SIG_PDU_Q, msg);
+}
+
+/*
+ * p 64: READY && SD PDU queued up
+ * arg is unused.
+ */
+static void
+sscop_ready_pduq(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ struct sscop_msg *msg;
+
+ if(sscop->rxq != 0) {
+ TAILQ_FOREACH(msg, &sscop->xbuf, link)
+ if(msg->rexmit)
+ break;
+ ASSERT(msg != NULL);
+ msg->rexmit = 0;
+ sscop->rxq--;
+ send_sd(sscop, msg->m, msg->seqno);
+ msg->poll_seqno = sscop->vt_ps;
+ if(sscop->poll_after_rex && sscop->rxq == 0)
+ goto poll; /* -> A */
+ else
+ goto maybe_poll; /* -> B */
+
+ }
+ if(MSGQ_EMPTY(&sscop->xq))
+ return;
+
+ if(sscop->vt_s >= sscop->vt_ms) {
+ /* Send windows closed */
+ TIMER_STOP(sscop, idle);
+ TIMER_RESTART(sscop, nr);
+ goto poll; /* -> A */
+
+ } else {
+ msg = MSGQ_GET(&sscop->xq);
+ msg->seqno = sscop->vt_s;
+ send_sd(sscop, msg->m, msg->seqno);
+ msg->poll_seqno = sscop->vt_ps;
+ sscop->vt_s++;
+ MSGQ_APPEND(&sscop->xbuf, msg);
+ goto maybe_poll; /* -> B */
+ }
+
+ /*
+ * p 65: Poll handling
+ */
+ maybe_poll: /* label B */
+ sscop->vt_pd++;
+ if(TIMER_ISACT(sscop, poll)) {
+ if(sscop->vt_pd < sscop->maxpd)
+ return;
+ } else {
+ if(TIMER_ISACT(sscop, idle)) {
+ TIMER_STOP(sscop, idle);
+ TIMER_RESTART(sscop, nr);
+ } else {
+ TIMER_STOP(sscop, ka);
+ }
+ if(sscop->vt_pd < sscop->maxpd) {
+ TIMER_RESTART(sscop, poll);
+ return;
+ }
+ }
+ poll: /* label A */
+ sscop->vt_ps++;
+ send_poll(sscop);
+ sscop->vt_pd = 0;
+ TIMER_RESTART(sscop, poll);
+}
+
+/*
+ * p 67: common recovery start
+ */
+static void
+sscop_recover(struct sscop *sscop)
+{
+ sscop->vt_cc = 1;
+ sscop->vt_sq++;
+
+ m_initialize_mr(sscop);
+ send_er(sscop);
+ m_prepare_recovery(sscop);
+
+ TIMER_RESTART(sscop, cc);
+
+ sscop_set_state(sscop, SSCOP_OUT_REC_PEND);
+}
+
+/*
+ * p 66: READY && SD PDU
+ * arg is received message.
+ */
+static void
+sscop_ready_sd(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+ u_int sn;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ msg->seqno = pdu.sscop_ns;
+
+ /* Fix padding */
+ MBUF_UNPAD(msg->m, pdu.sscop_pl);
+
+ if(msg->seqno >= sscop->vr_mr) {
+ /* message outside window */
+ if(sscop->vr_h < sscop->vr_mr) {
+ send_ustat(sscop, sscop->vr_h, sscop->vr_mr, -1);
+ sscop->vr_h = sscop->vr_mr;
+ }
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+
+ if(msg->seqno == sscop->vr_r) {
+ if(msg->seqno == sscop->vr_h) {
+ sscop->vr_r = msg->seqno + 1;
+ sscop->vr_h = msg->seqno + 1;
+
+ AAL_DATA(sscop, SSCOP_DATA_indication,
+ msg->m, msg->seqno);
+ msg->m = NULL;
+ SSCOP_MSG_FREE(msg);
+
+ return;
+ }
+ for(;;) {
+ AAL_DATA(sscop, SSCOP_DATA_indication,
+ msg->m, msg->seqno);
+ msg->m = NULL;
+ SSCOP_MSG_FREE(msg);
+
+ sscop->vr_r++;
+ if((msg = MSGQ_PEEK(&sscop->rbuf)) == NULL)
+ break;
+ sn = msg->seqno;
+ ASSERT(sn >= sscop->vr_r);
+ if(sn != sscop->vr_r)
+ break;
+ msg = MSGQ_GET(&sscop->rbuf);
+ }
+ return;
+ }
+
+ /* Messages were lost */
+
+ /* XXX Flow control */
+ if(msg->seqno == sscop->vr_h) {
+ QINSERT(&sscop->rbuf, msg);
+ sscop->vr_h++;
+ return;
+ }
+ if(sscop->vr_h < msg->seqno) {
+ QINSERT(&sscop->rbuf, msg);
+ send_ustat(sscop, sscop->vr_h, msg->seqno, -1);
+ sscop->vr_h = msg->seqno + 1;
+ return;
+ }
+
+ if(QFIND(&sscop->rbuf, msg->seqno) == NULL) {
+ QINSERT(&sscop->rbuf, msg);
+ return;
+ }
+
+ /* error: start recovery */
+ SSCOP_MSG_FREE(msg);
+ m_reset_data_xfer_timers(sscop);
+ MAAL_ERROR(sscop, 'Q', 0);
+ sscop_recover(sscop);
+}
+
+/*
+ * p 67: READY && POLL PDU
+ */
+static void
+sscop_ready_poll(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+ union seqno seqno;
+ u_int sn, nps;
+ struct SSCOP_MBUF_T *m;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ seqno.sscop_null = MBUF_STRIP32(msg->m);
+
+ if((u_int)pdu.sscop_ns < sscop->vr_h) {
+ SSCOP_MSG_FREE(msg);
+ m_reset_data_xfer_timers(sscop);
+ MAAL_ERROR(sscop, 'Q', 0);
+ sscop_recover(sscop);
+ return;
+ }
+ nps = seqno.sscop_n;
+
+ if((u_int)pdu.sscop_ns > sscop->vr_mr)
+ sscop->vr_h = sscop->vr_mr;
+ else
+ sscop->vr_h = pdu.sscop_ns;
+
+ SSCOP_MSG_FREE(msg);
+
+ /* build stat pdu */
+ if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) {
+ FAILURE("sscop: cannot allocate STAT");
+ return;
+ }
+ sn = sscop->vr_r;
+
+ while(sn != sscop->vr_h) {
+ /* loop through burst we already have */
+ for(;;) {
+ if(sn >= sscop->vr_h) {
+ seqno.sscop_null = 0;
+ seqno.sscop_n = sn;
+ MBUF_APPEND32(m, seqno.sscop_null);
+ goto out;
+ }
+ if(QFIND(&sscop->rbuf, sn) == NULL)
+ break;
+ sn++;
+ }
+
+ /* start of a hole */
+ seqno.sscop_null = 0;
+ seqno.sscop_n = sn;
+ MBUF_APPEND32(m, seqno.sscop_null);
+ if(MBUF_LEN(m)/4 >= sscop->maxstat) {
+ send_stat(sscop, nps, m);
+ if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) {
+ FAILURE("sscop: cannot allocate STAT");
+ return;
+ }
+ seqno.sscop_null = 0;
+ seqno.sscop_n = sn;
+ MBUF_APPEND32(m, seqno.sscop_null);
+ }
+ do {
+ sn++;
+ } while(sn < sscop->vr_h && !QFIND(&sscop->rbuf, sn));
+ seqno.sscop_null = 0;
+ seqno.sscop_n = sn;
+ MBUF_APPEND32(m, seqno.sscop_null);
+ }
+ out:
+ send_stat(sscop, nps, m);
+}
+
+/*
+ * p 69: READY && USTAT PDU
+ * arg is msg (freed)
+ */
+static void
+sscop_ready_ustat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+ union seqno nmr, sq1, sq2;
+ u_int cnt;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ nmr.sscop_null = MBUF_STRIP32(msg->m);
+ sq2.sscop_null = MBUF_STRIP32(msg->m);
+ sq1.sscop_null = MBUF_STRIP32(msg->m);
+
+ SSCOP_MSG_FREE(msg);
+
+ cnt = sq1.sscop_n - sq2.sscop_n;
+
+ if((u_int)pdu.sscop_ns < sscop->vt_a || (u_int)pdu.sscop_ns >= sscop->vt_s) {
+ VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
+ "USTAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u "
+ "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s));
+ goto err_f;
+ }
+
+ /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new
+ * next in sequence-SD-number of the receiver and means, it has all
+ * messages below N(R). Remove all message below N(R) from the
+ * transmission buffer. It may already be removed because of an
+ * earlier selective ACK in a STAT message.
+ */
+ while((msg = MSGQ_PEEK(&sscop->xbuf)) != NULL && msg->seqno < (u_int)pdu.sscop_ns) {
+ ASSERT(msg->seqno >= sscop->vt_a);
+ MSGQ_REMOVE(&sscop->xbuf, msg);
+ SSCOP_MSG_FREE(msg);
+ }
+
+ /* Update the in-sequence acknowledge and the send window */
+ sscop->vt_a = pdu.sscop_ns;
+ sscop->vt_ms = nmr.sscop_n;
+
+ /* check, that the range of requested re-transmissions is between
+ * the in-sequence-ack and the highest up-to-now transmitted SD
+ */
+ if(sq1.sscop_n >= sq2.sscop_n
+ || (u_int)sq1.sscop_n < sscop->vt_a
+ || (u_int)sq2.sscop_n >= sscop->vt_s) {
+ VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
+ "USTAT: seq1 or seq2 outside VT(A)...VT(S)-1 or seq1>=seq2:"
+ " seq1=%u seq2=%u VT(A)=%u VT(S)=%u",
+ sq1.sscop_n, sq2.sscop_n, sscop->vt_a, sscop->vt_s));
+ goto err_f;
+ }
+
+ /*
+ * Retransmit all messages from seq1 to seq2-1
+ */
+ do {
+ /*
+ * The message may not be in the transmit buffer if it was
+ * already acked by a STAT. This means, the receiver is
+ * confused.
+ */
+ if((msg = QFIND(&sscop->xbuf, sq1.sscop_n)) == NULL) {
+ VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
+ "USTAT: message %u not found in xmit buffer",
+ sq1.sscop_n));
+ goto err_f;
+ }
+
+ /*
+ * If it is not yet in the re-transmission queue, put it there
+ */
+ if(!msg->rexmit) {
+ msg->rexmit = 1;
+ sscop->rxq++;
+ sscop_signal(sscop, SIG_PDU_Q, msg);
+ }
+ sq1.sscop_n++;
+ } while(sq1.sscop_n != sq2.sscop_n);
+
+ /*
+ * report the re-transmission to the management
+ */
+ MAAL_ERROR(sscop, 'V', cnt);
+ return;
+
+ err_f:
+ m_reset_data_xfer_timers(sscop);
+ MAAL_ERROR(sscop, 'T', 0);
+ sscop_recover(sscop);
+}
+
+/*
+ * p 70: READY && STAT PDU
+ * arg is msg (freed).
+ */
+static void
+sscop_ready_stat(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+ union seqno nps, nmr;
+ u_int len, seq1, seq2, cnt;
+ struct sscop_msg *m;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+ nmr.sscop_null = MBUF_STRIP32(msg->m);
+ nps.sscop_null = MBUF_STRIP32(msg->m);
+
+ len = MBUF_LEN(msg->m) / 4;
+
+ if((u_int)nps.sscop_n < sscop->vt_pa
+ || (u_int)nps.sscop_n > sscop->vt_ps) {
+ SSCOP_MSG_FREE(msg);
+ m_reset_data_xfer_timers(sscop);
+ MAAL_ERROR(sscop, 'R', 0);
+ sscop_recover(sscop);
+ return;
+ }
+
+ if((u_int)pdu.sscop_ns < sscop->vt_a
+ || (u_int)pdu.sscop_ns > sscop->vt_s) {
+ /*
+ * The in-sequence acknowledge, i.e. the receivers's next
+ * expected in-sequence msg is outside the window between
+ * the transmitters in-sequence ack and highest seqno -
+ * the receiver seems to be confused.
+ */
+ VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
+ "STAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u "
+ "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s));
+ err_H:
+ SSCOP_MSG_FREE(msg);
+ m_reset_data_xfer_timers(sscop);
+ MAAL_ERROR(sscop, 'S', 0);
+ sscop_recover(sscop);
+ return;
+ }
+
+ /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new
+ * next in sequence-SD-number of the receiver and means, it has all
+ * messages below N(R). Remove all message below N(R) from the
+ * transmission buffer. It may already be removed because of an
+ * earlier selective ACK in a STAT message.
+ */
+ while((m = MSGQ_PEEK(&sscop->xbuf)) != NULL
+ && m->seqno < (u_int)pdu.sscop_ns) {
+ ASSERT(m->seqno >= sscop->vt_a);
+ MSGQ_REMOVE(&sscop->xbuf, m);
+ SSCOP_MSG_FREE(m);
+ }
+
+ /*
+ * Update in-sequence ack, poll-ack and send window.
+ */
+ sscop->vt_a = pdu.sscop_ns;
+ sscop->vt_pa = nps.sscop_n;
+ sscop->vt_ms = nmr.sscop_n;
+
+ cnt = 0;
+ if(len > 1) {
+ seq1 = MBUF_GET32(msg->m);
+ len--;
+ if(seq1 >= sscop->vt_s) {
+ VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
+ "STAT: seq1 >= VT(S): seq1=%u VT(S)=%u",
+ seq1, sscop->vt_s));
+ goto err_H;
+ }
+
+ for(;;) {
+ seq2 = MBUF_GET32(msg->m);
+ len--;
+ if(seq1 >= seq2 || seq2 > sscop->vt_s) {
+ VERBERR(sscop, SSCOP_DBG_ERR, (sscop,
+ sscop->aarg, "STAT: seq1 >= seq2 or "
+ "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u",
+ seq1, seq2, sscop->vt_s));
+ goto err_H;
+ }
+
+ do {
+ /*
+ * The receiver requests the re-transmission
+ * of some message, but has acknowledged it
+ * already in an earlier STAT (it isn't in the
+ * transmitt buffer anymore).
+ */
+ if((m = QFIND(&sscop->xbuf, seq1)) == NULL) {
+ VERBERR(sscop, SSCOP_DBG_ERR,
+ (sscop, sscop->aarg, "STAT: message"
+ " %u not found in xmit buffer",
+ seq1));
+ goto err_H;
+ }
+ if(m->poll_seqno < (u_int)nps.sscop_n
+ && (u_int)nps.sscop_n <= sscop->vt_ps)
+ if(!m->rexmit) {
+ m->rexmit = 1;
+ sscop->rxq++;
+ cnt++;
+ sscop_signal(sscop, SIG_PDU_Q, msg);
+ }
+ } while(++seq1 < seq2);
+
+ if(len == 0)
+ break;
+
+ seq2 = MBUF_GET32(msg->m);
+ len--;
+
+ if(seq1 >= seq2 || seq2 > sscop->vt_s) {
+ VERBERR(sscop, SSCOP_DBG_ERR, (sscop,
+ sscop->aarg, "STAT: seq1 >= seq2 or "
+ "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u",
+ seq1, seq2, sscop->vt_s));
+ goto err_H;
+ }
+
+ /* OK now the sucessful transmitted messages. Note, that
+ * some messages may already be out of the buffer because
+ * of earlier STATS */
+ do {
+ if(sscop->clear_buffers) {
+ if((m = QFIND(&sscop->xbuf, seq1)) != NULL) {
+ MSGQ_REMOVE(&sscop->xbuf, m);
+ SSCOP_MSG_FREE(m);
+ }
+ }
+ } while(++seq1 != seq2);
+
+ if(len == 0)
+ break;
+ }
+ MAAL_ERROR(sscop, 'V', cnt);
+ }
+ SSCOP_MSG_FREE(msg);
+
+ /* label L: */
+ if(sscop->vt_s >= sscop->vt_ms) {
+ /*
+ * The receiver has closed the window: report to management
+ */
+ if(sscop->credit) {
+ sscop->credit = 0;
+ MAAL_ERROR(sscop, 'W', 0);
+ }
+ } else if(!sscop->credit) {
+ /*
+ * The window was forcefully closed above, but
+ * now re-opened. Report to management.
+ */
+ sscop->credit = 1;
+ MAAL_ERROR(sscop, 'X', 0);
+ }
+
+ if(TIMER_ISACT(sscop, poll)) {
+ TIMER_RESTART(sscop, nr);
+ } else if(!TIMER_ISACT(sscop, idle)) {
+ TIMER_STOP(sscop, ka);
+ TIMER_STOP(sscop, nr);
+ TIMER_RESTART(sscop, idle);
+ }
+}
+
+/*
+ * P. 73: any state & UDATA_REQUEST
+ * arg is pdu (queued)
+ */
+static void
+sscop_udata_req(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MSGQ_APPEND(&sscop->uxq, msg);
+ sscop_signal(sscop, SIG_UPDU_Q, msg);
+}
+
+/*
+ * P. 73: any state & MDATA_REQUEST
+ * arg is pdu (queued)
+ */
+static void
+sscop_mdata_req(struct sscop *sscop, struct sscop_msg *msg)
+{
+ MSGQ_APPEND(&sscop->mxq, msg);
+ sscop_signal(sscop, SIG_MPDU_Q, msg);
+}
+
+/*
+ * P. 74: any state & UDATA queued
+ * no arg.
+ */
+static void
+sscop_upduq(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ struct sscop_msg *msg;
+
+ if(sscop->ll_busy)
+ return;
+ while((msg = MSGQ_GET(&sscop->uxq)) != NULL) {
+ send_ud(sscop, msg->m);
+ msg->m = NULL;
+ SSCOP_MSG_FREE(msg);
+ }
+}
+
+/*
+ * P. 74: any state & MDATA queued
+ * no arg.
+ */
+static void
+sscop_mpduq(struct sscop *sscop, struct sscop_msg *unused __unused)
+{
+ struct sscop_msg *msg;
+
+ if(sscop->ll_busy)
+ return;
+ while((msg = MSGQ_GET(&sscop->mxq)) != NULL) {
+ send_md(sscop, msg->m);
+ msg->m = NULL;
+ SSCOP_MSG_FREE(msg);
+ }
+}
+
+/*
+ * p 73: MD PDU
+ * arg is PDU
+ */
+static void
+sscop_md(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ MBUF_UNPAD(msg->m, pdu.sscop_pl);
+
+ MAAL_DATA(sscop, msg->m);
+ msg->m = NULL;
+ SSCOP_MSG_FREE(msg);
+}
+
+/*
+ * p 73: UD PDU
+ * arg is PDU
+ */
+static void
+sscop_ud(struct sscop *sscop, struct sscop_msg *msg)
+{
+ union pdu pdu;
+
+ pdu.sscop_null = MBUF_STRIP32(msg->m);
+
+ MBUF_UNPAD(msg->m, pdu.sscop_pl);
+
+ AAL_DATA(sscop, SSCOP_UDATA_indication, msg->m, 0);
+ msg->m = NULL;
+ SSCOP_MSG_FREE(msg);
+}
+
+
+/*
+ * p 33: IDLE & RETRIEVE
+ * p 39: IN_PEND & RETRIEVE
+ * p 42: OUT_DIS_PEND & RETRIEVE
+ * p 48: IN_RESYNC_PEND & RETRIEVE
+ * p 53: REC_PEND & RETRIEVE
+ * p 58: IN_REC_PEND & RETRIEVE
+ */
+static void
+sscop_retrieve(struct sscop *sscop, struct sscop_msg *msg)
+{
+ m_data_retrieval(sscop, msg->rexmit);
+ SSCOP_MSG_FREE(msg);
+}
+
+/************************************************************/
+/*
+ * GENERAL EVENT HANDLING
+ */
+
+/*
+ * State/event matrix.
+ *
+ * Entries marked with Z are not specified in Q.2110, but are added for
+ * the sake of stability.
+ */
+static struct {
+ void (*func)(struct sscop *, struct sscop_msg *);
+ int (*cond)(struct sscop *);
+} state_matrix[SSCOP_NSTATES][SIG_NUM] = {
+ /* SSCOP_IDLE */ {
+ /* SIG_BGN */ { sscop_idle_bgn, NULL },
+ /* SIG_BGAK */ { sscop_idle_bgak, NULL },
+ /* SIG_END */ { sscop_idle_end, NULL },
+ /* SIG_ENDAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_RS */ { sscop_idle_rs, NULL },
+ /* SIG_RSAK */ { sscop_idle_rsak, NULL },
+ /* SIG_BGREJ */ { sscop_idle_bgrej, NULL },
+ /* SIG_SD */ { sscop_idle_sd, NULL },
+ /* SIG_ER */ { sscop_idle_er, NULL },
+ /* SIG_POLL */ { sscop_idle_poll, NULL },
+ /* SIG_STAT */ { sscop_idle_stat, NULL },
+ /* SIG_USTAT */ { sscop_idle_ustat, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_idle_erak, NULL },
+ /* SIG_T_CC */ { NULL, NULL },
+ /* SIG_T_POLL */ { NULL, NULL },
+ /* SIG_T_KA */ { NULL, NULL },
+ /* SIG_T_NR */ { NULL, NULL },
+ /* SIG_T_IDLE */ { NULL, NULL },
+ /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
+ /* SIG_USER_DATA */ { NULL, NULL },
+ /* SIG_ESTAB_REQ */ { sscop_idle_establish_req, NULL },
+ /* SIG_ESTAB_RESP */ { NULL, NULL },
+ /* SIG_RELEASE_REQ */ { NULL, NULL },
+ /* SIG_RECOVER */ { NULL, NULL },
+ /* SIG_SYNC_REQ */ { NULL, NULL },
+ /* SIG_SYNC_RESP */ { NULL, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
+ },
+ /* SSCOP_OUT_PEND */ {
+ /* SIG_BGN */ { sscop_outpend_bgn, NULL },
+ /* SIG_BGAK */ { sscop_outpend_bgak, NULL },
+ /* SIG_END */ { sscop_ignore_pdu, NULL },
+ /* SIG_ENDAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_RS */ { sscop_ignore_pdu, NULL },
+ /* SIG_RSAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_BGREJ */ { sscop_outpend_bgrej, NULL },
+ /* SIG_SD */ { sscop_ignore_pdu, NULL },
+ /* SIG_ER */ { sscop_ignore_pdu, NULL },
+ /* SIG_POLL */ { sscop_ignore_pdu, NULL },
+ /* SIG_STAT */ { sscop_ignore_pdu, NULL },
+ /* SIG_USTAT */ { sscop_ignore_pdu, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_T_CC */ { sscop_outpend_tcc, NULL },
+ /* SIG_T_POLL */ { NULL, NULL },
+ /* SIG_T_KA */ { NULL, NULL },
+ /* SIG_T_NR */ { NULL, NULL },
+ /* SIG_T_IDLE */ { NULL, NULL },
+ /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
+ /* SIG_USER_DATA */ { NULL, NULL },
+ /* SIG_ESTAB_REQ */ { NULL, NULL },
+ /* SIG_ESTAB_RESP */ { NULL, NULL },
+ /* SIG_RELEASE_REQ */ { sscop_outpend_release_req, NULL },
+ /* SIG_RECOVER */ { NULL, NULL },
+ /* SIG_SYNC_REQ */ { NULL, NULL },
+ /* SIG_SYNC_RESP */ { NULL, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { NULL, NULL },
+ },
+ /* SSCOP_IN_PEND */ {
+ /* SIG_BGN */ { sscop_inpend_bgn, NULL },
+ /* SIG_BGAK */ { sscop_inpend_bgak, NULL },
+ /* SIG_END */ { sscop_inpend_end, NULL },
+ /* SIG_ENDAK */ { sscop_inpend_endak, NULL },
+ /* SIG_RS */ { sscop_inpend_rs, NULL },
+ /* SIG_RSAK */ { sscop_inpend_rsak, NULL },
+ /* SIG_BGREJ */ { sscop_inpend_bgrej, NULL },
+ /* SIG_SD */ { sscop_inpend_sd, NULL },
+ /* SIG_ER */ { sscop_inpend_er, NULL },
+ /* SIG_POLL */ { sscop_inpend_poll, NULL },
+ /* SIG_STAT */ { sscop_inpend_stat, NULL },
+ /* SIG_USTAT */ { sscop_inpend_ustat, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_inpend_erak, NULL },
+ /* SIG_T_CC */ { NULL, NULL },
+ /* SIG_T_POLL */ { NULL, NULL },
+ /* SIG_T_KA */ { NULL, NULL },
+ /* SIG_T_NR */ { NULL, NULL },
+ /* SIG_T_IDLE */ { NULL, NULL },
+ /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
+ /* SIG_USER_DATA */ { NULL, NULL },
+ /* SIG_ESTAB_REQ */ { NULL, NULL },
+ /* SIG_ESTAB_RESP */ { sscop_inpend_establish_resp, NULL },
+ /* SIG_RELEASE_REQ */ { sscop_inpend_release_req, NULL },
+ /* SIG_RECOVER */ { NULL, NULL },
+ /* SIG_SYNC_REQ */ { NULL, NULL },
+ /* SIG_SYNC_RESP */ { NULL, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
+ },
+ /* SSCOP_OUT_DIS_PEND */ {
+ /* SIG_BGN */ { sscop_outdis_bgn, NULL },
+ /* SIG_BGAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_END */ { sscop_outdis_end, NULL },
+ /* SIG_ENDAK */ { sscop_outdis_endak, NULL },
+ /* SIG_RS */ { sscop_ignore_pdu, NULL },
+ /* SIG_RSAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_BGREJ */ { sscop_outdis_endak, NULL },
+ /* SIG_SD */ { sscop_ignore_pdu, NULL },
+ /* SIG_ER */ { sscop_ignore_pdu, NULL },
+ /* SIG_POLL */ { sscop_ignore_pdu, NULL },
+ /* SIG_STAT */ { sscop_ignore_pdu, NULL },
+ /* SIG_USTAT */ { sscop_ignore_pdu, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_T_CC */ { sscop_outdis_cc, NULL },
+ /* SIG_T_POLL */ { NULL, NULL },
+ /* SIG_T_KA */ { NULL, NULL },
+ /* SIG_T_NR */ { NULL, NULL },
+ /* SIG_T_IDLE */ { NULL, NULL },
+ /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
+ /* SIG_USER_DATA */ { NULL, NULL },
+ /* SIG_ESTAB_REQ */ { sscop_outdis_establish_req, NULL },
+ /* SIG_ESTAB_RESP */ { NULL, NULL },
+ /* SIG_RELEASE_REQ */ { NULL, NULL },
+ /* SIG_RECOVER */ { NULL, NULL },
+ /* SIG_SYNC_REQ */ { NULL, NULL },
+ /* SIG_SYNC_RESP */ { NULL, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
+ },
+ /* SSCOP_OUT_RESYNC_PEND */ {
+ /* SIG_BGN */ { sscop_outsync_bgn, NULL },
+ /* SIG_BGAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_END */ { sscop_outsync_end, NULL },
+ /* SIG_ENDAK */ { sscop_outsync_endak, NULL },
+ /* SIG_RS */ { sscop_outsync_rs, NULL },
+ /* SIG_RSAK */ { sscop_outsync_rsak, NULL },
+ /* SIG_BGREJ */ { sscop_outsync_bgrej, NULL },
+ /* SIG_SD */ { sscop_ignore_pdu, NULL },
+ /* SIG_ER */ { sscop_ignore_pdu, NULL },
+ /* SIG_POLL */ { sscop_ignore_pdu, NULL },
+ /* SIG_STAT */ { sscop_ignore_pdu, NULL },
+ /* SIG_USTAT */ { sscop_ignore_pdu, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_T_CC */ { sscop_outsync_cc, NULL },
+ /* SIG_T_POLL */ { NULL, NULL },
+ /* SIG_T_KA */ { NULL, NULL },
+ /* SIG_T_NR */ { NULL, NULL },
+ /* SIG_T_IDLE */ { NULL, NULL },
+ /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
+ /* SIG_USER_DATA */ { NULL, NULL },
+ /* SIG_ESTAB_REQ */ { NULL, NULL },
+ /* SIG_ESTAB_RESP */ { NULL, NULL },
+ /* SIG_RELEASE_REQ */ { sscop_outsync_release_req, NULL },
+ /* SIG_RECOVER */ { NULL, NULL },
+ /* SIG_SYNC_REQ */ { NULL, NULL },
+ /* SIG_SYNC_RESP */ { NULL, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { NULL, NULL },
+ },
+ /* SSCOP_IN_RESYNC_PEND */ {
+ /* SIG_BGN */ { sscop_insync_bgn, NULL },
+ /* SIG_BGAK */ { sscop_insync_bgak, NULL },
+ /* SIG_END */ { sscop_insync_end, NULL },
+ /* SIG_ENDAK */ { sscop_insync_endak, NULL },
+ /* SIG_RS */ { sscop_insync_rs, NULL },
+ /* SIG_RSAK */ { sscop_insync_rsak, NULL },
+ /* SIG_BGREJ */ { sscop_insync_bgrej, NULL },
+ /* SIG_SD */ { sscop_insync_sd, NULL },
+ /* SIG_ER */ { sscop_insync_er, NULL },
+ /* SIG_POLL */ { sscop_insync_poll, NULL },
+ /* SIG_STAT */ { sscop_insync_stat, NULL },
+ /* SIG_USTAT */ { sscop_insync_ustat, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_insync_erak, NULL },
+ /* SIG_T_CC */ { NULL, NULL },
+ /* SIG_T_POLL */ { NULL, NULL },
+ /* SIG_T_KA */ { NULL, NULL },
+ /* SIG_T_NR */ { NULL, NULL },
+ /* SIG_T_IDLE */ { NULL, NULL },
+ /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
+ /* SIG_USER_DATA */ { NULL, NULL },
+ /* SIG_ESTAB_REQ */ { NULL, NULL },
+ /* SIG_ESTAB_RESP */ { NULL, NULL },
+ /* SIG_RELEASE_REQ */ { sscop_insync_release_req, NULL },
+ /* SIG_RECOVER */ { NULL, NULL },
+ /* SIG_SYNC_REQ */ { NULL, NULL },
+ /* SIG_SYNC_RESP */ { sscop_insync_sync_resp, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
+ },
+ /* SSCOP_OUT_REC_PEND */ {
+ /* SIG_BGN */ { sscop_outrec_bgn, NULL },
+ /* SIG_BGAK */ { sscop_outrec_bgak, NULL },
+ /* SIG_END */ { sscop_outrec_end, NULL },
+ /* SIG_ENDAK */ { sscop_outrec_endak, NULL },
+ /* SIG_RS */ { sscop_outrec_rs, NULL },
+ /* SIG_RSAK */ { sscop_outrec_rsak, NULL },
+ /* SIG_BGREJ */ { sscop_outrec_bgrej, NULL },
+ /* SIG_SD */ { sscop_ignore_pdu, NULL },
+ /* SIG_ER */ { sscop_outrec_er, NULL },
+ /* SIG_POLL */ { sscop_ignore_pdu, NULL },
+ /* SIG_STAT */ { sscop_ignore_pdu, NULL },
+ /* SIG_USTAT */ { sscop_ignore_pdu, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_outrec_erak, NULL },
+ /* SIG_T_CC */ { sscop_outrec_cc, NULL },
+ /* SIG_T_POLL */ { NULL, NULL },
+ /* SIG_T_KA */ { NULL, NULL },
+ /* SIG_T_NR */ { NULL, NULL },
+ /* SIG_T_IDLE */ { NULL, NULL },
+ /* SIG_PDU_Q */ { sscop_outrec_pduq, NULL },
+ /* SIG_USER_DATA */ { sscop_outrec_userdata, NULL },
+ /* SIG_ESTAB_REQ */ { NULL, NULL },
+ /* SIG_ESTAB_RESP */ { NULL, NULL },
+ /* SIG_RELEASE_REQ */ { sscop_outrec_release_req, NULL },
+ /* SIG_RECOVER */ { NULL, NULL },
+ /* SIG_SYNC_REQ */ { sscop_outrec_sync_req, NULL },
+ /* SIG_SYNC_RESP */ { NULL, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { NULL, NULL },
+ },
+ /* SSCOP_REC_PEND */ {
+ /* SIG_BGN */ { sscop_rec_bgn, NULL },
+ /* SIG_BGAK */ { sscop_rec_bgak, NULL },
+ /* SIG_END */ { sscop_rec_end, NULL },
+ /* SIG_ENDAK */ { sscop_rec_endak, NULL },
+ /* SIG_RS */ { sscop_rec_rs, NULL },
+ /* SIG_RSAK */ { sscop_rec_rsak, NULL },
+ /* SIG_BGREJ */ { sscop_rec_bgrej, NULL },
+ /* SIG_SD */ { sscop_ignore_pdu, NULL },
+ /* SIG_ER */ { sscop_rec_er, NULL },
+ /* SIG_POLL */ { sscop_ignore_pdu, NULL },
+ /* SIG_STAT */ { sscop_rec_stat, NULL },
+ /* SIG_USTAT */ { sscop_rec_ustat, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_T_CC */ { NULL, NULL },
+ /* SIG_T_POLL */ { NULL, NULL },
+ /* SIG_T_KA */ { NULL, NULL },
+ /* SIG_T_NR */ { NULL, NULL },
+ /* SIG_T_IDLE */ { NULL, NULL },
+ /* SIG_PDU_Q */ { sscop_rec_pduq, NULL },
+ /* SIG_USER_DATA */ { NULL, NULL },
+ /* SIG_ESTAB_REQ */ { NULL, NULL },
+ /* SIG_ESTAB_RESP */ { NULL, NULL },
+ /* SIG_RELEASE_REQ */ { sscop_rec_release_req, NULL },
+ /* SIG_RECOVER */ { sscop_rec_recover, NULL },
+ /* SIG_SYNC_REQ */ { sscop_rec_sync_req, NULL },
+ /* SIG_SYNC_RESP */ { NULL, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
+ },
+ /* SSCOP_IN_REC_PEND */ {
+ /* SIG_BGN */ { sscop_inrec_bgn, NULL },
+ /* SIG_BGAK */ { sscop_inrec_bgak, NULL },
+ /* SIG_END */ { sscop_inrec_end, NULL },
+ /* SIG_ENDAK */ { sscop_inrec_endak, NULL },
+ /* SIG_RS */ { sscop_inrec_rs, NULL },
+ /* SIG_RSAK */ { sscop_inrec_rsak, NULL },
+ /* SIG_BGREJ */ { sscop_inrec_bgrej, NULL },
+ /* SIG_SD */ { sscop_inrec_sd, NULL },
+ /* SIG_ER */ { sscop_inrec_er, NULL },
+ /* SIG_POLL */ { sscop_inrec_poll, NULL },
+ /* SIG_STAT */ { sscop_inrec_stat, NULL },
+ /* SIG_USTAT */ { sscop_inrec_ustat, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_inrec_erak, NULL },
+ /* SIG_T_CC */ { NULL, NULL },
+ /* SIG_T_POLL */ { NULL, NULL },
+ /* SIG_T_KA */ { NULL, NULL },
+ /* SIG_T_NR */ { NULL, NULL },
+ /* SIG_T_IDLE */ { NULL, NULL },
+ /* SIG_PDU_Q */ { sscop_inrec_pduq, NULL },
+ /* SIG_USER_DATA */ { NULL, NULL },
+ /* SIG_ESTAB_REQ */ { NULL, NULL },
+ /* SIG_ESTAB_RESP */ { NULL, NULL },
+ /* SIG_RELEASE_REQ */ { sscop_inrec_release_req, NULL },
+ /* SIG_RECOVER */ { sscop_inrec_recover, NULL },
+ /* SIG_SYNC_REQ */ { sscop_inrec_sync_req, NULL },
+ /* SIG_SYNC_RESP */ { NULL, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
+ },
+ /* SSCOP_READY */ {
+ /* SIG_BGN */ { sscop_ready_bgn, NULL },
+ /* SIG_BGAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_END */ { sscop_ready_end, NULL },
+ /* SIG_ENDAK */ { sscop_ready_endak, NULL },
+ /* SIG_RS */ { sscop_ready_rs, NULL },
+ /* SIG_RSAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_BGREJ */ { sscop_ready_bgrej, NULL },
+ /* SIG_SD */ { sscop_ready_sd, NULL },
+ /* SIG_ER */ { sscop_ready_er, NULL },
+ /* SIG_POLL */ { sscop_ready_poll, NULL },
+ /* SIG_STAT */ { sscop_ready_stat, NULL },
+ /* SIG_USTAT */ { sscop_ready_ustat, NULL },
+ /* SIG_UD */ { sscop_ud, NULL },
+ /* SIG_MD */ { sscop_md, NULL },
+ /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
+ /* SIG_T_CC */ { NULL, NULL },
+ /* SIG_T_POLL */ { sscop_ready_tpoll, NULL },
+ /* SIG_T_KA */ { sscop_ready_tka, NULL },
+ /* SIG_T_NR */ { sscop_ready_nr, NULL },
+ /* SIG_T_IDLE */ { sscop_ready_tidle, NULL },
+ /* SIG_PDU_Q */ { sscop_ready_pduq, c_ready_pduq },
+ /* SIG_USER_DATA */ { sscop_ready_userdata, NULL },
+ /* SIG_ESTAB_REQ */ { NULL, NULL },
+ /* SIG_ESTAB_RESP */ { NULL, NULL },
+ /* SIG_RELEASE_REQ */ { sscop_ready_release_req, NULL },
+ /* SIG_RECOVER */ { NULL, NULL },
+ /* SIG_SYNC_REQ */ { sscop_ready_sync_req, NULL },
+ /* SIG_SYNC_RESP */ { NULL, NULL },
+ /* SIG_UDATA */ { sscop_udata_req, NULL },
+ /* SIG_MDATA */ { sscop_mdata_req, NULL },
+ /* SIG_UPDU_Q */ { sscop_upduq, NULL },
+ /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
+ /* SIG_RETRIEVE */ { NULL, NULL },
+ }
+};
+
+/*
+ * Try to execute a signal. It is executed if
+ * - it is illegal (in this case it is effectively ignored)
+ * - it has no condition
+ * - its condition is true
+ * If it has a condition and that is false, the function does nothing and
+ * returns 0.
+ * If the signal gets executed, the signal function is responsible to release
+ * the message (if any).
+ */
+static int
+sig_exec(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
+{
+ void (*func)(struct sscop *, struct sscop_msg *);
+ int (*cond)(struct sscop *);
+
+ func = state_matrix[sscop->state][sig].func;
+ cond = state_matrix[sscop->state][sig].cond;
+
+ if(func == NULL) {
+ VERBOSE(sscop, SSCOP_DBG_BUG, (sscop, sscop->aarg,
+ "no handler for %s in state %s - ignored",
+ events[sig], states[sscop->state]));
+ SSCOP_MSG_FREE(msg);
+ return 1;
+ }
+ if(cond == NULL || (*cond)(sscop)) {
+ VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg,
+ "executing %s in %s", events[sig],
+ states[sscop->state]));
+ (*func)(sscop, msg);
+ return 1;
+ }
+ VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg,
+ "delaying %s in %s", events[sig],
+ states[sscop->state]));
+
+ return 0;
+}
+
+/*
+ * Deliver a signal to the given sscop
+ * If it is delivered from inside a signal handler - queue it. If not,
+ * execute it. After execution loop through the queue and execute all
+ * pending signals. Signals, that cannot be executed because of entry
+ * conditions are skipped.
+ */
+static void
+sscop_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
+{
+ struct sscop_sig *s;
+
+ VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
+ "got signal %s in state %s%s", events[sig],
+ states[sscop->state], sscop->in_sig ? " -- queuing" : ""));
+
+ SIG_ALLOC(s);
+ if(s == NULL) {
+ FAILURE("sscop: cannot allocate signal");
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ s->sig = sig;
+ s->msg = msg;
+ SIGQ_APPEND(&sscop->sigs, s);
+
+ if(!sscop->in_sig)
+ handle_sigs(sscop);
+}
+
+/*
+ * Loop through the signal queue until we can't execute any signals.
+ */
+static void
+handle_sigs(struct sscop *sscop)
+{
+ struct sscop_sig *s;
+ sscop_sigq_head_t dsigs, q;
+ int exec;
+
+ sscop->in_sig++;
+
+ /*
+ * Copy the current signal queue to the local one and empty
+ * the signal queue. Then loop through the signals. After one
+ * pass we have a list of delayed signals because of entry
+ * conditions and a new list of signals. Merge them. Repeat until
+ * the signal queue is either empty or contains only delayed signals.
+ */
+ SIGQ_INIT(&q);
+ SIGQ_INIT(&dsigs);
+ do {
+ exec = 0;
+
+ /*
+ * Copy signal list and make sscop list empty
+ */
+ SIGQ_MOVE(&sscop->sigs, &q);
+
+ /*
+ * Loop through the list
+ */
+ while((s = SIGQ_GET(&q)) != NULL) {
+ if(sig_exec(sscop, s->sig, s->msg)) {
+ exec = 1;
+ SIG_FREE(s);
+ } else {
+ SIGQ_APPEND(&dsigs, s);
+ }
+ }
+
+ /*
+ * Merge lists by inserting delayed signals in front of
+ * the signal list. preserving the order.
+ */
+ SIGQ_PREPEND(&dsigs, &sscop->sigs);
+ } while(exec);
+ sscop->in_sig--;
+}
+
+/*
+ * Save a signal that should be executed only if state changes.
+ */
+static void
+sscop_save_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
+{
+ struct sscop_sig *s;
+
+ SIG_ALLOC(s);
+ if(s == NULL) {
+ FAILURE("sscop: cannot allocate signal");
+ SSCOP_MSG_FREE(msg);
+ return;
+ }
+ s->sig = sig;
+ s->msg = msg;
+ SIGQ_APPEND(&sscop->saved_sigs, s);
+}
+
+/*
+ * Set a new state. If signals are waiting for a state change - append them to
+ * the signal queue, so they get executed.
+ */
+static void
+sscop_set_state(struct sscop *sscop, u_int nstate)
+{
+ VERBOSE(sscop, SSCOP_DBG_STATE, (sscop, sscop->aarg,
+ "changing state from %s to %s",
+ states[sscop->state], states[nstate]));
+
+ sscop->state = nstate;
+ SIGQ_MOVE(&sscop->saved_sigs, &sscop->sigs);
+}
+
+void
+sscop_setdebug(struct sscop *sscop, u_int n)
+{
+ sscop->debug = n;
+}
+
+u_int
+sscop_getdebug(const struct sscop *sscop)
+{
+ return (sscop->debug);
+}
diff --git a/sys/contrib/ngatm/netnatm/saal/sscfu.h b/sys/contrib/ngatm/netnatm/saal/sscfu.h
new file mode 100644
index 000000000000..3aaa9270d3ff
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/saal/sscfu.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/saal/sscfu.h,v 1.4 2004/07/08 08:22:15 brandt Exp $
+ *
+ * Public include file for UNI SSCF
+ */
+#ifndef _NETNATM_SAAL_SSCFU_H_
+#define _NETNATM_SAAL_SSCFU_H_
+
+#include <sys/types.h>
+#include <netnatm/saal/sscopdef.h>
+#include <netnatm/saal/sscfudef.h>
+
+/*
+ * Define how a buffer looks like.
+ */
+#ifdef _KERNEL
+#ifdef __FreeBSD__
+#define SSCFU_MBUF_T mbuf
+#endif
+#else
+#define SSCFU_MBUF_T uni_msg
+#endif
+
+struct SSCFU_MBUF_T;
+struct sscfu;
+
+/* functions to be supplied by the SSCOP user */
+struct sscfu_funcs {
+ /* upper (SAAL) interface output */
+ void (*send_upper)(struct sscfu *, void *, enum saal_sig,
+ struct SSCFU_MBUF_T *);
+
+ /* lower (SSCOP) interface output */
+ void (*send_lower)(struct sscfu *, void *, enum sscop_aasig,
+ struct SSCFU_MBUF_T *, u_int);
+
+ /* function to move the SSCOP window */
+ void (*window)(struct sscfu *, void *, u_int);
+
+ /* debugging function */
+ void (*verbose)(struct sscfu *, void *, const char *, ...)
+ __printflike(3, 4);
+};
+
+/* Function defined by the SSCF-UNI code */
+
+/* allocate and initialize a new SSCF instance */
+struct sscfu *sscfu_create(void *, const struct sscfu_funcs *);
+
+/* destroy an SSCF instance and free all resources */
+void sscfu_destroy(struct sscfu *);
+
+/* reset the SSCF to the released state */
+void sscfu_reset(struct sscfu *);
+
+/* lower input interface (SSCOP signals) */
+void sscfu_input(struct sscfu *, enum sscop_aasig, struct SSCFU_MBUF_T *, u_int);
+
+/* upper input interface (SAAL) */
+int sscfu_saalsig(struct sscfu *, enum saal_sig, struct SSCFU_MBUF_T *);
+
+/* retrieve the current state */
+enum sscfu_state sscfu_getstate(const struct sscfu *);
+
+/* char'ify signals and states */
+const char *sscfu_signame(enum saal_sig);
+const char *sscfu_statename(enum sscfu_state);
+
+/* retrieve the default set of parameters for SSCOP */
+u_int sscfu_getdefparam(struct sscop_param *);
+
+/* get/set debugging flags */
+void sscfu_setdebug(struct sscfu *, u_int);
+u_int sscfu_getdebug(const struct sscfu *);
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/saal/sscfudef.h b/sys/contrib/ngatm/netnatm/saal/sscfudef.h
new file mode 100644
index 000000000000..08882f2a9bc2
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/saal/sscfudef.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/saal/sscfudef.h,v 1.4 2004/07/08 08:22:16 brandt Exp $
+ *
+ * Definitions of UNI SSCF constants.
+ */
+#ifndef _NETNATM_SAAL_SSCFUDEF_H_
+#define _NETNATM_SAAL_SSCFUDEF_H_
+
+/*
+ * Signals at the upper boundary of the SSCF.
+ */
+enum saal_sig {
+ SAAL_ESTABLISH_request, /* U -> SAAL: (UU) */
+ SAAL_ESTABLISH_indication, /* SAAL -> U: (UU) */
+ SAAL_ESTABLISH_confirm, /* SAAL -> U: (UU) */
+ SAAL_RELEASE_request, /* U -> SAAL: (UU) */
+ SAAL_RELEASE_confirm, /* SAAL -> U: */
+ SAAL_RELEASE_indication, /* SAAL -> U: (UU) */
+ SAAL_DATA_request, /* U -> SAAL: (DATA) */
+ SAAL_DATA_indication, /* SAAL -> U: (DATA) */
+ SAAL_UDATA_request, /* U -> SAAL: (UDATA) */
+ SAAL_UDATA_indication, /* SAAL -> U: (UDATA) */
+};
+
+/*
+ * States of the SSCF
+ */
+enum sscfu_state {
+ SSCFU_RELEASED, /* 1/1 */
+ SSCFU_AWAITING_ESTABLISH, /* 2/2 */
+ SSCFU_AWAITING_RELEASE, /* 4/10 */
+ SSCFU_ESTABLISHED, /* 3/4 */
+ SSCFU_RESYNC, /* 2/5 */
+};
+
+/*
+ * Debugging flags
+ */
+enum {
+ SSCFU_DBG_LSIG = 0x01,
+ SSCFU_DBG_ERR = 0x02,
+ SSCFU_DBG_STATE = 0x04,
+ SSCFU_DBG_EXEC = 0x08,
+};
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/saal/sscfupriv.h b/sys/contrib/ngatm/netnatm/saal/sscfupriv.h
new file mode 100644
index 000000000000..b4a1299ac108
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/saal/sscfupriv.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/saal/sscfupriv.h,v 1.3 2003/09/19 12:02:03 hbb Exp $
+ *
+ * Private SSCF-UNI definitions.
+ */
+#ifdef _KERNEL
+#ifdef __FreeBSD__
+#include <netgraph/atm/sscfu/ng_sscfu_cust.h>
+#endif
+#else
+#include "sscfucust.h"
+#endif
+
+/*
+ * Structure for signal queueing.
+ */
+struct sscfu_sig {
+ sscfu_sigq_link_t link; /* link to next signal */
+ enum saal_sig sig; /* the signal */
+ struct SSCFU_MBUF_T *m; /* associated message */
+};
+
+struct sscfu {
+ enum sscfu_state state; /* SSCF state */
+ const struct sscfu_funcs *funcs; /* func vector */
+ void *aarg; /* user arg */
+ int inhand; /* need to queue signals */
+ sscfu_sigq_head_t sigs; /* signal queue */
+ u_int debug; /* debugging flags */
+};
+
+/*
+ * Debugging
+ */
+#ifdef SSCFU_DEBUG
+#define VERBOSE(S,M,F) if ((S)->debug & (M)) (S)->funcs->verbose F
+#else
+#define VERBOSE(S,M,F)
+#endif
diff --git a/sys/contrib/ngatm/netnatm/saal/sscop.h b/sys/contrib/ngatm/netnatm/saal/sscop.h
new file mode 100644
index 000000000000..8574a1581791
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/saal/sscop.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/saal/sscop.h,v 1.4 2004/07/08 08:22:16 brandt Exp $
+ *
+ * External interface to sscop.
+ */
+#ifndef _NETNATM_SAAL_SSCOP_H_
+#define _NETNATM_SAAL_SSCOP_H_
+
+#include <netnatm/saal/sscopdef.h>
+
+/*
+ * Define how a buffer looks like.
+ */
+#ifdef _KERNEL
+#ifdef __FreeBSD__
+#define SSCOP_MBUF_T mbuf
+#endif
+#else
+#define SSCOP_MBUF_T uni_msg
+#endif
+
+struct SSCOP_MBUF_T;
+struct sscop;
+
+/*
+ * Vector for user functions
+ */
+struct sscop_funcs {
+ /* management signal from SSCOP */
+ void (*send_manage)(struct sscop *, void *, enum sscop_maasig,
+ struct SSCOP_MBUF_T *, u_int, u_int);
+
+ /* AAL signal from SSCOP */
+ void (*send_upper)(struct sscop *, void *, enum sscop_aasig,
+ struct SSCOP_MBUF_T *, u_int);
+
+ /* send a PDU to the wire */
+ void (*send_lower)(struct sscop *, void *,
+ struct SSCOP_MBUF_T *);
+
+ /* print a message */
+ void (*verbose)(struct sscop *, void *, const char *, ...)
+ __printflike(3,4);
+
+#ifndef _KERNEL
+ /* start a timer */
+ void *(*start_timer)(struct sscop *, void *, u_int,
+ void (*)(void *));
+
+ /* stop a timer */
+ void (*stop_timer)(struct sscop *, void *, void *);
+#endif
+};
+
+/* Function defined by the SSCOP code */
+
+/* create a new SSCOP instance and initialize to default values */
+struct sscop *sscop_create(void *, const struct sscop_funcs *);
+
+/* destroy an SSCOP instance */
+void sscop_destroy(struct sscop *);
+
+/* get the current parameters of an SSCOP */
+void sscop_getparam(const struct sscop *, struct sscop_param *);
+
+/* set new parameters in an SSCOP */
+int sscop_setparam(struct sscop *, struct sscop_param *, u_int *);
+
+/* deliver an signal to the SSCOP */
+int sscop_aasig(struct sscop *, enum sscop_aasig, struct SSCOP_MBUF_T *, u_int);
+
+/* deliver an management signal to the SSCOP */
+int sscop_maasig(struct sscop *, enum sscop_maasig, struct SSCOP_MBUF_T *);
+
+/* SSCOP input function */
+void sscop_input(struct sscop *, struct SSCOP_MBUF_T *);
+
+/* Move the window by a given number of messages. Return the new window */
+u_int sscop_window(struct sscop *, u_int);
+
+/* declare the lower layer busy or not busy */
+u_int sscop_setbusy(struct sscop *, int);
+
+/* retrieve the state */
+enum sscop_state sscop_getstate(const struct sscop *);
+
+/* map signals to strings */
+const char *sscop_msigname(enum sscop_maasig);
+const char *sscop_signame(enum sscop_aasig);
+const char *sscop_statename(enum sscop_state);
+
+/* set/get debugging state */
+void sscop_setdebug(struct sscop *, u_int);
+u_int sscop_getdebug(const struct sscop *);
+
+/* reset the instance */
+void sscop_reset(struct sscop *);
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/saal/sscopdef.h b/sys/contrib/ngatm/netnatm/saal/sscopdef.h
new file mode 100644
index 000000000000..ec6716461c34
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/saal/sscopdef.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $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.
+ */
+#ifndef _NETNATM_SAAL_SSCOPDEF_H_
+#define _NETNATM_SAAL_SSCOPDEF_H_
+
+#include <sys/types.h>
+#ifdef _KERNEL
+#include <sys/stdint.h>
+#else
+#include <stdint.h>
+#endif
+
+/*
+ * AA-interface signals
+ */
+enum sscop_aasig {
+ SSCOP_ESTABLISH_request, /* <- UU, BR */
+ SSCOP_ESTABLISH_indication, /* -> UU */
+ SSCOP_ESTABLISH_response, /* <- UU, BR */
+ SSCOP_ESTABLISH_confirm, /* -> UU */
+
+ SSCOP_RELEASE_request, /* <- UU */
+ SSCOP_RELEASE_indication, /* -> UU, SRC */
+ SSCOP_RELEASE_confirm, /* -> */
+
+ SSCOP_DATA_request, /* <- MU */
+ SSCOP_DATA_indication, /* -> MU, SN */
+
+ SSCOP_UDATA_request, /* <- MU */
+ SSCOP_UDATA_indication, /* -> MU */
+
+ SSCOP_RECOVER_indication, /* -> */
+ SSCOP_RECOVER_response, /* <- */
+
+ SSCOP_RESYNC_request, /* <- UU */
+ SSCOP_RESYNC_indication, /* -> UU */
+ SSCOP_RESYNC_response, /* <- */
+ SSCOP_RESYNC_confirm, /* -> */
+
+ SSCOP_RETRIEVE_request, /* <- RN */
+ SSCOP_RETRIEVE_indication, /* -> MU */
+ SSCOP_RETRIEVE_COMPL_indication,/* -> */
+};
+
+enum sscop_maasig {
+ SSCOP_MDATA_request, /* <- MU */
+ SSCOP_MDATA_indication, /* -> MU */
+ SSCOP_MERROR_indication, /* -> CODE, CNT */
+};
+
+/*
+ * Values for retrieval. Numbers in SSCOP are 24bit, so
+ * we can use the large values
+ */
+enum {
+ SSCOP_MAXSEQNO = 0xffffff,
+
+ SSCOP_RETRIEVE_UNKNOWN = SSCOP_MAXSEQNO + 1,
+ SSCOP_RETRIEVE_TOTAL = SSCOP_MAXSEQNO + 2,
+};
+
+/*
+ * SSCOP states
+ */
+enum sscop_state {
+ SSCOP_IDLE, /* initial state */
+ SSCOP_OUT_PEND, /* outgoing connection pending */
+ SSCOP_IN_PEND, /* incoming connection pending */
+ SSCOP_OUT_DIS_PEND, /* outgoing disconnect pending */
+ SSCOP_OUT_RESYNC_PEND, /* outgoing resynchronisation pending */
+ SSCOP_IN_RESYNC_PEND, /* incoming resynchronisation pending */
+ SSCOP_OUT_REC_PEND, /* outgoing recovery pending */
+ SSCOP_REC_PEND, /* recovery response pending */
+ SSCOP_IN_REC_PEND, /* incoming recovery pending */
+ SSCOP_READY, /* data transfer ready */
+};
+#define SSCOP_NSTATES 10
+
+struct sscop_param {
+ uint32_t timer_cc; /* timer_cc in msec */
+ uint32_t timer_poll; /* timer_poll im msec */
+ uint32_t timer_keep_alive;/* timer_keep_alive in msec */
+ uint32_t timer_no_response;/*timer_no_response in msec */
+ uint32_t timer_idle; /* timer_idle in msec */
+ uint32_t maxk; /* maximum user data in bytes */
+ uint32_t maxj; /* maximum u-u info in bytes */
+ uint32_t maxcc; /* max. retransmissions for control packets */
+ uint32_t maxpd; /* max. vt(pd) before sending poll */
+ uint32_t maxstat; /* max. number of elements in stat list */
+ uint32_t mr; /* initial window */
+ uint32_t flags; /* flags */
+};
+enum {
+ SSCOP_ROBUST = 0x0001, /* atmf/97-0216 robustness */
+ SSCOP_POLLREX = 0x0002, /* send POLL after retransmit */
+};
+
+enum {
+ SSCOP_SET_TCC = 0x0001,
+ SSCOP_SET_TPOLL = 0x0002,
+ SSCOP_SET_TKA = 0x0004,
+ SSCOP_SET_TNR = 0x0008,
+ SSCOP_SET_TIDLE = 0x0010,
+ SSCOP_SET_MAXK = 0x0020,
+ SSCOP_SET_MAXJ = 0x0040,
+ SSCOP_SET_MAXCC = 0x0080,
+ SSCOP_SET_MAXPD = 0x0100,
+ SSCOP_SET_MAXSTAT = 0x0200,
+ SSCOP_SET_MR = 0x0400,
+ SSCOP_SET_ROBUST = 0x0800,
+ SSCOP_SET_POLLREX = 0x1000,
+
+ SSCOP_SET_ALLMASK = 0x1fff,
+};
+
+enum {
+ SSCOP_DBG_USIG = 0x0001,
+ SSCOP_DBG_TIMER = 0x0002,
+ SSCOP_DBG_BUG = 0x0004,
+ SSCOP_DBG_INSIG = 0x0008,
+ SSCOP_DBG_STATE = 0x0010,
+ SSCOP_DBG_PDU = 0x0020,
+ SSCOP_DBG_ERR = 0x0040,
+ SSCOP_DBG_EXEC = 0x0080,
+ SSCOP_DBG_FLOW = 0x0100,
+};
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/saal/sscoppriv.h b/sys/contrib/ngatm/netnatm/saal/sscoppriv.h
new file mode 100644
index 000000000000..e2b055530b1f
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/saal/sscoppriv.h
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/saal/sscoppriv.h,v 1.4 2004/07/08 08:22:17 brandt Exp $
+ *
+ * Private SSCOP definitions.
+ *
+ */
+#ifdef _KERNEL
+#ifdef __FreeBSD__
+#include <netgraph/atm/sscop/ng_sscop_cust.h>
+#endif
+#else /* !_KERNEL */
+#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
+ */
+union pdu {
+ u_int sscop_null;
+ struct {
+#if _BYTE_ORDER == _BIG_ENDIAN
+ u_int pl : 2; /* pad length */
+ u_int : 1; /* reserved field */
+ u_int s : 1; /* source */
+ u_int type : 4; /* PDU type */
+ u_int ns : 24; /* sequence number */
+#else
+ u_int ns : 24; /* sequence number */
+ u_int type : 4; /* PDU type */
+ u_int s : 1; /* source */
+ u_int : 1; /* reserved field */
+ u_int pl : 2; /* pad length */
+#endif
+ } ss;
+};
+#define sscop_pl ss.pl
+#define sscop_s ss.s
+#define sscop_type ss.type
+#define sscop_ns ss.ns
+
+/*
+ * seqno list entry format
+ */
+union seqno {
+ u_int sscop_null;
+ struct {
+#if _BYTE_ORDER == _BIG_ENDIAN
+ u_int : 8; /* pad */
+ u_int n : 24; /* seqno */
+#else
+ u_int n : 24; /* seqno */
+ u_int : 8; /* pad */
+#endif
+ } ss;
+};
+#define sscop_n ss.n
+
+/*
+ * Begin pdu
+ */
+union bgn {
+ u_int sscop_null;
+ struct {
+#if _BYTE_ORDER == _BIG_ENDIAN
+ u_int : 24; /* reserved */
+ u_int bgns : 8; /* VT_MR */
+#else
+ u_int bgns : 8; /* VT_MR */
+ u_int : 24; /* reserved */
+#endif
+ } ss;
+};
+#define sscop_bgns ss.bgns
+
+/*
+ * pdu types
+ */
+enum pdu_type {
+ PDU_BGN = 0x1, /* request initialization */
+ PDU_BGAK = 0x2, /* request acknowledgement */
+ PDU_END = 0x3, /* disconnect command */
+ PDU_ENDAK = 0x4, /* disconnect acknowledgement */
+ PDU_RS = 0x5, /* resynchronisation command */
+ PDU_RSAK = 0x6, /* resynchronisation acknowledgement */
+ PDU_BGREJ = 0x7, /* connection reject */
+ PDU_SD = 0x8, /* sequenced connection-mode data */
+ PDU_ER = 0x9, /* recovery command */
+ PDU_POLL = 0xa, /* xmit state info with req. for recv state */
+ PDU_STAT = 0xb, /* solicited receiver state info */
+ PDU_USTAT = 0xc, /* unsolicited receiver state info */
+ PDU_UD = 0xd, /* unumbered user data */
+ PDU_MD = 0xe, /* unumbered management data */
+ PDU_ERAK = 0xf, /* recovery acknowledgement */
+};
+
+
+/*
+ * These are all signals, that are used by SSCOP. Don't change the order or
+ * number without also changing the associated tables.
+ */
+enum sscop_sigtype {
+ /* received PDU's */
+ SIG_BGN, /* request initialization */
+ SIG_BGAK, /* request acknowledgement */
+ SIG_END, /* disconnect command */
+ SIG_ENDAK, /* disconnect acknowledgement */
+ SIG_RS, /* resynchronisation command */
+ SIG_RSAK, /* resynchronisation acknowledgement */
+ SIG_BGREJ, /* connection reject */
+ SIG_SD, /* sequenced connection-mode data */
+ SIG_ER, /* recovery command */
+ SIG_POLL, /* xmitter state info with req for recv state */
+ SIG_STAT, /* solicited receiver state info */
+ SIG_USTAT, /* unsolicited receiver state info */
+ SIG_UD, /* unumbered user data */
+ SIG_MD, /* unumbered management data */
+ SIG_ERAK, /* recovery acknoledgement */
+
+ /* timer expiry */
+ SIG_T_CC, /* CC timer */
+ SIG_T_POLL, /* POLL timer */
+ SIG_T_KA, /* KEEP ALIVE timer */
+ SIG_T_NR, /* NO RESPONSE timer */
+ SIG_T_IDLE, /* IDLE timer */
+
+ /* user originated signals */
+ SIG_PDU_Q, /* PDU enqueued pseudosignal */
+ SIG_USER_DATA, /* user data request */
+ SIG_ESTAB_REQ, /* establish connection request */
+ SIG_ESTAB_RESP, /* establish connection response */
+ SIG_RELEASE_REQ, /* release connection request */
+ SIG_RECOVER, /* automatic recover response */
+ SIG_SYNC_REQ, /* resynchronisation request */
+ SIG_SYNC_RESP, /* resynchronisation response */
+ SIG_UDATA, /* UDATA request */
+ SIG_MDATA, /* MDATA request */
+ SIG_UPDU_Q, /* UDATA PDU enqueued pseudosignal */
+ SIG_MPDU_Q, /* MDATA PDU enqueued pseudosignal */
+ SIG_RETRIEVE, /* RETRIEVE */
+
+ /* number of signals */
+ SIG_NUM
+};
+
+/*
+ * This is a message as contained in a sscop message queue. It holds a pointer
+ * to the real message.
+ */
+struct sscop_msg {
+ sscop_msgq_link_t link;
+ u_int seqno; /* seq no */
+ u_int poll_seqno; /* poll seqno (for messages in xmit buffer) */
+ u_int rexmit; /* in retransmission queue? */
+ struct SSCOP_MBUF_T *m; /* the message */
+};
+
+/*
+ * This structure is used to hold signals in the signal queue
+ */
+struct sscop_sig {
+ sscop_sigq_link_t link; /* next signal */
+ enum sscop_sigtype sig; /* THE signal */
+ struct sscop_msg *msg; /* signal argument (message) */
+};
+
+/*
+ * This structure holds the entire sscop state
+ */
+struct sscop {
+ enum sscop_state state; /* current state */
+ const struct sscop_funcs *funcs;
+
+ /* send state */
+ u_int vt_s; /* seqno for next pdu first time transmitted */
+ u_int vt_ps; /* current poll seqno */
+ u_int vt_a; /* next expected in-sequence sd pdu */
+ u_int vt_pa; /* poll seqno of next stat pdu */
+ u_int vt_ms; /* maximum allowed send sd seqno */
+ u_int vt_pd; /* poll data state */
+ u_int vt_cc; /* connection control state */
+ u_int vt_sq; /* transmitter connection sequence */
+
+ /* receive state */
+ u_int vr_r; /* receive state */
+ u_int vr_h; /* highes expected state */
+ u_int vr_mr; /* maximum acceptable */
+ u_int vr_sq; /* receiver connection state */
+
+ /* timers */
+ sscop_timer_t t_cc; /* timer_CC */
+ sscop_timer_t t_nr; /* timer_NO_RESPONSE */
+ sscop_timer_t t_ka; /* timer KEEP_ALIVE */
+ sscop_timer_t t_poll; /* timer_POLL */
+ sscop_timer_t t_idle; /* idle timer */
+
+ /* maximum values */
+ u_int maxj; /* maximum uu-info */
+ u_int maxk; /* maximum info */
+ u_int maxcc; /* maximum number of bgn, end, er and rs */
+ u_int maxpd; /* maximum value of vt_pd */
+ u_int maxstat; /* maximum length of list */
+ u_int timercc; /* connection control timer */
+ u_int timerka; /* keep alive timer */
+ u_int timernr; /* no response timer */
+ u_int timerpoll; /* polling */
+ u_int timeridle; /* idle timer */
+ u_int robustness; /* atmf/97-0216 robustness enhancement */
+ u_int poll_after_rex; /* optional POLL after re-transmission */
+ u_int mr; /* initial window */
+
+ /*
+ * buffers and queues.
+ * All expect the xq hold SD PDUs.
+ */
+ sscop_msgq_head_t xq; /* xmit queue (input from user before xmit) */
+ sscop_msgq_head_t uxq; /* UD xmit queue */
+ sscop_msgq_head_t mxq; /* MD xmit queue */
+ sscop_msgq_head_t xbuf; /* transmission buffer (SD PDUs transmitted) */
+ int rxq; /* number of PDUs in retransmission queue */
+ sscop_msgq_head_t rbuf; /* receive buffer (SD PDUs) */
+ int last_end_src; /* source field from last xmitted end pdu */
+ int clear_buffers; /* flag */
+ int credit; /* send window not closed */
+ u_int ll_busy; /* lower layer busy */
+ u_int rs_mr; /* N(MR) in last RS PDU */
+ u_int rs_sq; /* N(SQ) in last RS PDU */
+ struct SSCOP_MBUF_T *uu_bgn; /* last UU data */
+ struct SSCOP_MBUF_T *uu_bgak; /* ... */
+ struct SSCOP_MBUF_T *uu_bgrej; /* ... */
+ struct SSCOP_MBUF_T *uu_end; /* ... */
+ struct SSCOP_MBUF_T *uu_rs; /* ... */
+
+ /* signal queues */
+ sscop_sigq_head_t sigs; /* saved signals */
+ sscop_sigq_head_t saved_sigs; /* saved signals */
+ int in_sig; /* in signal handler */
+
+ /* debugging */
+ u_int debug;
+
+ /* AA interface */
+ void *aarg;
+};
+
+
+/*
+ * Default values for SSCOP
+ */
+enum {
+ MAXK = 4096,
+ MAXMAXK = 65528,
+ MAXJ = 4096,
+ MAXMAXJ = 65524,
+ MAXCC = 4,
+ MAXSTAT = 67,
+ MAXPD = 25,
+ MAXMR = 128, /* ??? */
+ TIMERCC = 1000,
+ TIMERKA = 2000,
+ TIMERNR = 7000,
+ TIMERPOLL = 750,
+ TIMERIDLE = 15000,
+};
+
+/*
+ * Sequence number arithmetic
+ */
+#define SEQNO_DIFF(A,B) (((A) < (B)) ? ((A) + (1<<24) - (B)) : ((A) - (B)))
+
+/*
+ * Debugging
+ */
+#ifdef SSCOP_DEBUG
+#define VERBOSE(S,M,F) if ((S)->debug & (M)) (S)->funcs->verbose F
+#define VERBERR(S,M,F) if ((S)->debug & (M)) (S)->funcs->verbose F
+#define ISVERBOSE(S,M) ((S)->debug & (M))
+#else
+#define VERBOSE(S,M,F)
+#define VERBERR(S,M,F)
+#define ISVERBOSE(S,M) (0)
+#endif
diff --git a/sys/contrib/ngatm/netnatm/sig/genmsgcpyc.awk b/sys/contrib/ngatm/netnatm/sig/genmsgcpyc.awk
new file mode 100644
index 000000000000..be61925c977a
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/genmsgcpyc.awk
@@ -0,0 +1,80 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/sig/genmsgcpyc.awk,v 1.4 2004/07/08 08:22:18 brandt Exp $
+#
+# Generate copy functions for messages
+#
+function begin() {
+}
+
+function first_entry() {
+ print "/* This file was created automatically"
+ print " * Source file: " id
+ print " * $FreeBSD$"
+ print " */"
+ print ""
+ print "#include <netnatm/msg/unistruct.h>"
+ print "#include <netnatm/sig/unimsgcpy.h>"
+}
+
+function end() {
+}
+
+function start_message() {
+}
+
+function end_message() {
+ print ""
+ print "void"
+ print "copy_msg_" msg "(struct uni_" msg " *src, struct uni_" msg " *dst)"
+ print "{"
+ for(i = 0; i < cnt; i++) {
+ if(ienum[i] != "-") {
+ print "\tu_int s, d;"
+ print ""
+ break
+ }
+ }
+ for(i = 0; i < cnt; i++) {
+ ie = iename[i]
+ if(ierep[i]) {
+ print "\tif(IE_ISGOOD(src->" ie "_repeat))"
+ print "\t\tdst->" ie "_repeat = src->" ie "_repeat;"
+ }
+ if(ienum[i] != "-") {
+ print "\tfor(s = d = 0; s < "ienum[i]"; s++)"
+ print "\t\tif(IE_ISGOOD(src->"ie"[s]))"
+ print "\t\t\tdst->"ie"[d++] = src->"ie"[s];"
+ } else {
+ print "\tif(IE_ISGOOD(src->"ie"))"
+ print "\t\tdst->"ie" = src->"ie";"
+ }
+ }
+ print "}"
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/genmsgcpyh.awk b/sys/contrib/ngatm/netnatm/sig/genmsgcpyh.awk
new file mode 100644
index 000000000000..f9b44f2b168d
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/genmsgcpyh.awk
@@ -0,0 +1,55 @@
+#
+# Copyright (c) 2001-2003
+# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+# All rights reserved.
+#
+# 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.
+#
+# Author: Hartmut Brandt <harti@freebsd.org>
+#
+# $Begemot: libunimsg/netnatm/sig/genmsgcpyh.awk,v 1.4 2004/07/08 08:22:19 brandt Exp $
+#
+# Generate copy functions for messages
+#
+function begin() {
+}
+
+function first_entry() {
+ print "/* This file was created automatically"
+ print " * Source file: " id
+ print " * $FreeBSD$"
+ print " */"
+ print ""
+}
+
+function end() {
+}
+
+function start_message() {
+}
+
+function end_message() {
+ print ""
+ print "void"
+ print "copy_msg_" msg "(struct uni_" msg " *src, struct uni_" msg " *dst);"
+ print ""
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_call.c b/sys/contrib/ngatm/netnatm/sig/sig_call.c
new file mode 100644
index 000000000000..d2e3b7f9af2e
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/sig_call.c
@@ -0,0 +1,4310 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/sig_call.c,v 1.65 2004/08/05 07:11:00 brandt Exp $
+ *
+ * Call instance handling
+ *
+ * Note:
+ * In all functions that handle messages from the user or from
+ * the SAAL, commit memory allocation always at the begin of the
+ * function. If allocation fails, ignore saal messages and
+ * respond with an error to user messages.
+ */
+
+#include <netnatm/unimsg.h>
+#include <netnatm/saal/sscfudef.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/sig/uni.h>
+
+#include <netnatm/sig/unipriv.h>
+#include <netnatm/sig/unimkmsg.h>
+#include <netnatm/sig/unimsgcpy.h>
+
+static enum call_state state_compat(struct call *, enum uni_callstate);
+static void respond_drop_party_ack(struct call *, struct uni_ie_epref *, u_int);
+
+
+#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME,
+static const char *const call_sigs[] = {
+ DEF_CALL_SIGS
+};
+#undef DEF_PRIV_SIG
+
+TIMER_FUNC_CALL(t308, t308_func)
+TIMER_FUNC_CALL(t303, t303_func)
+TIMER_FUNC_CALL(t301, t301_func)
+TIMER_FUNC_CALL(t310, t310_func)
+TIMER_FUNC_CALL(t313, t313_func)
+TIMER_FUNC_CALL(t322, t322_func)
+
+const struct callstates callstates[] = {
+ [CALLST_NULL] = { "NU0", UNI_CALLSTATE_U0 },
+ [CALLST_U1] = { "U1", UNI_CALLSTATE_U1 },
+ [CALLST_U3] = { "U3", UNI_CALLSTATE_U3 },
+ [CALLST_U4] = { "U4", UNI_CALLSTATE_U4 },
+ [CALLST_U6] = { "U6", UNI_CALLSTATE_U6 },
+ [CALLST_U7] = { "U7", UNI_CALLSTATE_U7 },
+ [CALLST_U8] = { "U8", UNI_CALLSTATE_U8 },
+ [CALLST_U9] = { "U9", UNI_CALLSTATE_U9 },
+ [CALLST_U10] = { "U10", UNI_CALLSTATE_U10 },
+ [CALLST_U11] = { "U11", UNI_CALLSTATE_U11 },
+ [CALLST_U12] = { "U12", UNI_CALLSTATE_U12 },
+ [CALLST_N1] = { "N1", UNI_CALLSTATE_N1 },
+ [CALLST_N3] = { "N3", UNI_CALLSTATE_N3 },
+ [CALLST_N4] = { "N4", UNI_CALLSTATE_N4 },
+ [CALLST_N6] = { "N6", UNI_CALLSTATE_N6 },
+ [CALLST_N7] = { "N7", UNI_CALLSTATE_N7 },
+ [CALLST_N8] = { "N8", UNI_CALLSTATE_N8 },
+ [CALLST_N9] = { "N9", UNI_CALLSTATE_N9 },
+ [CALLST_N10] = { "N10", UNI_CALLSTATE_N10 },
+ [CALLST_N11] = { "N11", UNI_CALLSTATE_N11 },
+ [CALLST_N12] = { "N12", UNI_CALLSTATE_N12 },
+};
+
+static void unx_send_add_party_rej(struct call *c, struct uni_all *u);
+
+static __inline void
+set_call_state(struct call *c, enum call_state state)
+{
+ ASSERT(state == CALLST_NULL ||
+ (c->uni->proto == UNIPROTO_UNI40U &&
+ (state >= CALLST_U1 && state <= CALLST_U12)) ||
+ (c->uni->proto == UNIPROTO_UNI40N &&
+ (state >= CALLST_N1 && state <= CALLST_N12)),
+ ("setting wrong callstate for proto %u: %u", c->uni->proto, state));
+
+ if (c->cstate != state) {
+ VERBOSE(c->uni, UNI_FAC_CALL, 1, "call %d/%d %s -> %s",
+ c->cref, c->mine, callstates[c->cstate].name,
+ callstates[state].name);
+ c->cstate = state;
+ }
+}
+
+static enum uni_callstate
+map_callstate(enum call_state state)
+{
+ return (callstates[state].ext);
+}
+
+/*
+ * Find the call. Assume, that the cref is one of a message just received.
+ * That is, if the call reference flag is 0 it is his call, if it is 1 it
+ * is my call.
+ */
+struct call *
+uni_find_call(struct uni *uni, struct uni_cref *cref)
+{
+ struct call *c;
+
+ TAILQ_FOREACH(c, &uni->calls, link)
+ if (c->cref == cref->cref && (!c->mine == !cref->flag))
+ return (c);
+ return (NULL);
+}
+struct call *
+uni_find_callx(struct uni *uni, u_int cref, u_int mine)
+{
+ struct call *c;
+
+ TAILQ_FOREACH(c, &uni->calls, link)
+ if (c->cref == cref && !c->mine == !mine)
+ return (c);
+ return (NULL);
+}
+
+/*
+ * 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, uint32_t cookie)
+{
+ struct call *c;
+ struct uniapi_call_created *ind;
+ struct uni_msg *api;
+
+ if ((c = CALL_ALLOC()) == NULL)
+ return (NULL);
+
+ if ((ind = ALLOC_API(struct uniapi_call_created, api)) == NULL) {
+ CALL_FREE(c);
+ return (NULL);
+ }
+ ind->cref.cref = cref;
+ ind->cref.flag = mine;
+
+ c->uni = uni;
+ c->type = CALL_NULL;
+ c->cref = cref;
+ c->mine = mine;
+ c->cstate = CALLST_NULL;
+ TAILQ_INIT(&c->parties);
+
+ TIMER_INIT_CALL(c, t301);
+ TIMER_INIT_CALL(c, t303);
+ TIMER_INIT_CALL(c, t308);
+ TIMER_INIT_CALL(c, t310);
+ TIMER_INIT_CALL(c, t313);
+ TIMER_INIT_CALL(c, t322);
+
+ TAILQ_INSERT_HEAD(&uni->calls, c, link);
+
+ uni->funcs->uni_output(uni, uni->arg, UNIAPI_CALL_CREATED, cookie, api);
+
+ VERBOSE(c->uni, UNI_FAC_CALL, 1, "created call %u/%s",
+ c->cref, c->mine ? "mine" : "his");
+
+ return (c);
+}
+
+struct call *
+uni_create_new_call(struct uni *uni, uint32_t cookie)
+{
+ struct call *c;
+ uint32_t old = uni->cref_alloc++;
+
+ again:
+ if (uni->cref_alloc == (1 << 23))
+ uni->cref_alloc = 1;
+ if (uni->cref_alloc == old)
+ return (NULL); /* all crefs exhausted!!! */
+ TAILQ_FOREACH(c, &uni->calls, link)
+ if (c->mine && c->cref == uni->cref_alloc) {
+ uni->cref_alloc++;
+ goto again;
+ }
+ return (uni_create_call(uni, uni->cref_alloc, 1, cookie));
+}
+
+/*
+ * Assume timers are all stopped. Memory is not actually freed unless
+ * the reference count drops to 0.
+ * This function is assumed to remove the call from the parent UNI's
+ * call queue.
+ */
+void
+uni_destroy_call(struct call *c, int really)
+{
+ struct uniapi_call_destroyed *ind;
+ struct uni_msg *api;
+ struct party *p;
+
+ VERBOSE(c->uni, UNI_FAC_CALL, 1, "destroying call %u/%s",
+ c->cref, c->mine ? "mine" : "his");
+
+ TIMER_DESTROY_CALL(c, t301);
+ TIMER_DESTROY_CALL(c, t303);
+ TIMER_DESTROY_CALL(c, t308);
+ TIMER_DESTROY_CALL(c, t310);
+ TIMER_DESTROY_CALL(c, t313);
+ TIMER_DESTROY_CALL(c, t322);
+ TAILQ_REMOVE(&c->uni->calls, c, link);
+
+ uni_delsig(c->uni, SIG_CALL, c, NULL);
+
+ while ((p = TAILQ_FIRST(&c->parties)) != NULL) {
+ TAILQ_REMOVE(&c->parties, p, link);
+ uni_destroy_party(p, really);
+ }
+
+ if (!really) {
+ ind = ALLOC_API(struct uniapi_call_destroyed, api);
+ if (ind != NULL) {
+ ind->cref.cref = c->cref;
+ ind->cref.flag = c->mine;
+
+ uni_enq_coord(c->uni, SIGO_CALL_DESTROYED, 0, api);
+ }
+
+ uni_enq_call(c, SIGC_CALL_DELETE, 0, NULL, NULL);
+ return;
+ }
+
+ CALL_FREE(c);
+}
+
+static void
+allocate_epref(struct call *c, struct uni_ie_epref *epref)
+{
+ struct party *p;
+ uint32_t old = c->epref_alloc++;
+
+ again:
+ if (c->epref_alloc == (1 << 15))
+ c->epref_alloc = 0;
+ if (c->epref_alloc == old)
+ return; /* all crefs exhausted!!! */
+ TAILQ_FOREACH(p, &c->parties, link)
+ if (p->epref == c->epref_alloc) {
+ c->epref_alloc++;
+ goto again;
+ }
+ IE_SETPRESENT(*epref);
+ epref->flag = 0;
+ epref->epref = c->epref_alloc;
+
+ epref->h.coding = UNI_CODING_ITU;
+ epref->h.act = UNI_IEACT_DEFAULT;
+}
+
+static void
+reset_all_timers(struct call *c)
+{
+ TIMER_STOP_CALL(c, t301);
+ TIMER_STOP_CALL(c, t303);
+ TIMER_STOP_CALL(c, t308);
+ TIMER_STOP_CALL(c, t310);
+ TIMER_STOP_CALL(c, t313);
+ TIMER_STOP_CALL(c, t322);
+}
+
+/*
+ * Initiate call clearing because of a problem. This is label D in
+ * the SDLs and is called from many places.
+ * The call must have constructed the cause IE in struct call.
+ *
+ * Q.2971:Call-Control-U 27/39
+ * Q.2971:Call-Control-N 28/39
+ *
+ * Memory problems are handled differently here: we simply ignore them
+ * by not sending messages or user indications. Because of T308 we
+ * may be lucky to send the message in a second run.
+ *
+ * It is assumed, that the cause for the release is constructed by
+ * the calling function in uni->cause.
+ */
+static void
+clear_callD(struct call *c)
+{
+ struct uni_msg *api;
+ struct uniapi_release_indication *ind;
+ struct party *p;
+ struct uni_all *rel;
+
+ /*
+ * Send indication to API
+ */
+ if ((ind = ALLOC_API(struct uniapi_release_indication, api)) != NULL) {
+ ind->release.hdr.cref.cref = c->cref;
+ ind->release.hdr.cref.flag = c->mine;
+ ind->release.hdr.act = UNI_MSGACT_DEFAULT;
+ ind->release.cause[0] = c->uni->cause;
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_indication, 0, api);
+ }
+
+ reset_all_timers(c);
+
+ if (c->type == CALL_LEAF || c->type == CALL_ROOT) {
+ TAILQ_FOREACH(p, &c->parties, link) {
+ uni_enq_party(p, SIGP_RELEASE_request, 0, NULL, NULL);
+ }
+ }
+
+ memset(&c->msg_release, 0, sizeof(c->msg_release));
+ c->msg_release.cause[0] = c->uni->cause;
+
+ if ((rel = UNI_ALLOC()) != NULL) {
+ rel->u.release = c->msg_release;
+ MK_MSG_ORIG(rel, UNI_RELEASE, c->cref, !c->mine);
+ (void)uni_send_output(rel, c->uni);
+ UNI_FREE(rel);
+ }
+
+ TIMER_START_CALL(c, t308, c->uni->timer308);
+ c->cnt308 = 0;
+
+ if (c->uni->proto == UNIPROTO_UNI40N)
+ set_call_state(c, CALLST_N12);
+ else
+ set_call_state(c, CALLST_U11);
+}
+
+
+/**********************************************************************/
+/*
+ * SETUP message in state NULL
+ *
+ * Q.2971:Call-Control-U 4/39
+ * Q.2971:Call-Control-N 4/39
+ */
+static void
+un0_setup(struct call *c, struct uni_msg *m, struct uni_all *u,
+ enum call_state new_state)
+{
+ struct uni_all *resp;
+ struct party *p;
+ struct uniapi_setup_indication *ind;
+ struct uni_msg *api;
+ enum verify v;
+
+ if ((ind = ALLOC_API(struct uniapi_setup_indication, api)) == NULL) {
+ clear:
+ uni_destroy_call(c, 0);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ MANDATE_IE(c->uni, u->u.setup.bearer, UNI_IE_BEARER);
+ MANDATE_IE(c->uni, u->u.setup.traffic, UNI_IE_TRAFFIC);
+ MANDATE_IE(c->uni, u->u.setup.called, UNI_IE_CALLED);
+
+ /*
+ * UNI4.0: 9.1.1.2 Notes 2/3
+ */
+ if (!IE_ISPRESENT(u->u.setup.qos))
+ MANDATE_IE(c->uni, u->u.setup.exqos, UNI_IE_EXQOS);
+ if (!IE_ISPRESENT(u->u.setup.exqos))
+ MANDATE_IE(c->uni, u->u.setup.qos, UNI_IE_QOS);
+
+ /*
+ * Q.2971
+ */
+ if (IE_ISGOOD(u->u.setup.bearer) &&
+ u->u.setup.bearer.cfg == UNI_BEARER_MP) {
+ if (IE_ISGOOD(u->u.setup.epref) &&
+ u->u.setup.epref.flag == 1) {
+ IE_SETERROR(u->u.setup.epref);
+ (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF,
+ u->u.setup.epref.h.act, UNI_IERR_BAD);
+ }
+ uni_mandate_epref(c->uni, &u->u.setup.epref);
+ }
+
+ v = uni_verify(c->uni, u->u.hdr.act);
+ switch (v) {
+
+ case VFY_RAI:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ UNI_CALLSTATE_U0, NULL, 0);
+ /* FALLTHRU */
+ case VFY_I:
+ uni_msg_destroy(api);
+ goto clear;
+
+ case VFY_RAIM:
+ case VFY_CLR:
+ if ((resp = UNI_ALLOC()) != NULL) {
+ MK_MSG_RESP(resp, UNI_RELEASE_COMPL, &u->u.hdr.cref);
+ uni_vfy_collect_ies(c->uni);
+ resp->u.release_compl.cause[0] = c->uni->cause;
+ uni_send_output(resp, c->uni);
+ UNI_FREE(resp);
+ }
+ uni_msg_destroy(api);
+ goto clear;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(new_state), NULL, 0);
+ /* FALLTHRU */
+ case VFY_OK:
+ break;
+ }
+
+ if (u->u.setup.bearer.cfg == UNI_BEARER_P2P) {
+ c->type = CALL_P2P;
+
+ } else {
+ c->type = CALL_LEAF;
+ if ((p = uni_create_party(c, &u->u.setup.epref)) == NULL) {
+ uni_msg_destroy(api);
+ goto clear;
+ }
+ uni_enq_party(p, SIGP_SETUP, 0, NULL, NULL);
+ }
+
+ ind->setup.hdr = u->u.hdr;
+ copy_msg_setup(&u->u.setup, &ind->setup);
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_SETUP_indication, 0, api);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_call_state(c, new_state);
+}
+
+/*
+ * Setup.request from user
+ *
+ * Q.2971:Call-Control-U 4/39 (U0)
+ * Q.2971:Call-Control-N 4/39 (N0)
+ */
+static void
+un0_setup_request(struct call *c, struct uni_msg *m, uint32_t cookie,
+ enum call_state new_state)
+{
+ struct uniapi_setup_request *arg =
+ uni_msg_rptr(m, struct uniapi_setup_request *);
+ struct uni_setup *setup = &arg->setup;
+ struct uni_all *out;
+ struct party *p;
+
+ if (!IE_ISGOOD(setup->bearer)) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_MISSING_IE, cookie);
+ uni_destroy_call(c, 0);
+ return;
+ }
+ if ((out = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ uni_destroy_call(c, 0);
+ return;
+ }
+
+ c->msg_setup = *setup;
+
+ if (IE_ISGOOD(setup->connid))
+ c->connid = setup->connid;
+
+ if (setup->bearer.cfg == UNI_BEARER_P2P) {
+ c->type = CALL_P2P;
+ } else {
+ c->type = CALL_ROOT;
+
+ /*
+ * If the user didn't specify a endpoint reference,
+ * use 0. Use IE_IGNORE accoring to Appendix II Q.2971
+ */
+ if (!IE_ISPRESENT(c->msg_setup.epref)) {
+ MK_IE_EPREF(c->msg_setup.epref, 0, 0);
+ if (c->uni->proto == UNIPROTO_UNI40N)
+ c->msg_setup.epref.h.act = UNI_IEACT_IGNORE;
+
+ } else if (!IE_ISGOOD(c->msg_setup.epref)) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ uni_destroy_call(c, 0);
+ return;
+ }
+ if ((p = uni_create_partyx(c, 0, 1, cookie)) == NULL) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ uni_destroy_call(c, 0);
+ return;
+ }
+ uni_enq_party(p, SIGP_SETUP_request, cookie, NULL, NULL);
+ }
+
+ uni_msg_destroy(m);
+
+ out->u.setup = c->msg_setup;
+ MK_MSG_ORIG(out, UNI_SETUP, c->cref, !c->mine);
+ (void)uni_send_output(out, c->uni);
+ UNI_FREE(out);
+
+ TIMER_START_CALL(c, t303, c->uni->timer303);
+ c->cnt303 = 0;
+
+ set_call_state(c, new_state);
+
+ uniapi_call_error(c, UNIAPI_OK, cookie);
+}
+
+/*
+ * CALL PROCEEDING message
+ *
+ * Q.2971:Call-Control-U 6/39 (in U1)
+ * Q.2971:Call-Control-N 11/39 (in N6)
+ */
+static void
+u1n6_call_proc(struct call *c, struct uni_msg *m, struct uni_all *u,
+ enum call_state new_state)
+{
+ struct uni_call_proc *cp = &u->u.call_proc;
+ struct uniapi_proceeding_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_proceeding_indication, api);
+ if (ind == NULL) {
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ if (!IE_ISPRESENT(c->connid) && !IE_ISGOOD(cp->connid))
+ uni_mandate_ie(c->uni, UNI_IE_CONNID);
+
+ /*
+ * Q.2971: L3MU_01_03 requests us to ignore the message if
+ * the EPREF is missing.
+ */
+ if (c->msg_setup.bearer.cfg == UNI_BEARER_MP &&
+ IE_ISPRESENT(c->msg_setup.epref)) {
+ if (!IE_ISPRESENT(cp->epref))
+ uni_mandate_ie(c->uni, UNI_IE_EPREF); \
+
+ else if (IE_ISGOOD(cp->epref) &&
+ (cp->epref.flag != 1 ||
+ cp->epref.epref != c->msg_setup.epref.epref)) {
+ IE_SETERROR(cp->epref);
+ (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF,
+ cp->epref.h.act, UNI_IERR_BAD);
+ }
+ }
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ /* FALLTHRU */
+ case VFY_I:
+ uni_msg_destroy(api);
+ goto ignore;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ report:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), NULL, 0);
+ uni_msg_destroy(api);
+ goto ignore;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ if (c->type == CALL_ROOT && !IE_ISGOOD(cp->epref))
+ goto report;
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(new_state), NULL, 0);
+ /* FALLTHRU */
+ case VFY_OK:
+ break;
+ }
+
+ TIMER_STOP_CALL(c, t303);
+
+ if (IE_ISGOOD(cp->connid))
+ c->connid = cp->connid;
+
+ ind->call_proc.hdr = u->u.hdr;
+ copy_msg_call_proc(cp, &ind->call_proc);
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_PROCEEDING_indication, 0, api);
+
+ TIMER_START_CALL(c, t310, c->uni->timer310);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_call_state(c, new_state);
+}
+
+/*
+ * T303 tick.
+ *
+ * Q.2971:Call-Control-U 6/39
+ * Q.2971:Call-Control-N 11/39
+ */
+static void
+u1n6_t303(struct call *c)
+{
+ struct uni_all *msg;
+ struct uniapi_release_confirm *conf;
+ struct uni_msg *api;
+
+ VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T303 tick %d",
+ c->cref, c->mine ? "mine" : "his", c->cnt303 + 1);
+
+ if (++c->cnt303 < c->uni->init303) {
+ if ((msg = UNI_ALLOC()) != NULL) {
+ msg->u.setup = c->msg_setup;
+ MK_MSG_ORIG(msg, UNI_SETUP, c->cref, !c->mine);
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+ }
+ TIMER_START_CALL(c, t303, c->uni->timer303);
+ return;
+ }
+
+ /*
+ * Send indication to API
+ */
+ if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) {
+ conf->release.hdr.cref.cref = c->cref;
+ conf->release.hdr.cref.flag = c->mine;
+ conf->release.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_NO_RESPONSE);
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_confirm, 0, api);
+ }
+
+ /*
+ * send to party (there may be only one)
+ */
+ if (c->type == CALL_ROOT && !TAILQ_EMPTY(&c->parties)) {
+ uni_enq_party(TAILQ_FIRST(&c->parties),
+ SIGP_RELEASE_confirm, 0, NULL, NULL);
+ }
+ uni_destroy_call(c, 0);
+}
+
+/*
+ * T310 (Call Proceeding) timer tick.
+ *
+ * Q.2971:Call-Control-U 7/39
+ * Q.2971:Call-Control-N 17/39
+ */
+static void
+u3n9_t310(struct call *c)
+{
+ VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T310 tick",
+ c->cref, c->mine ? "mine" : "his");
+
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_NO_RESPONSE);
+ clear_callD(c);
+}
+
+/*
+ * T301 (Alerting) timer tick.
+ *
+ * Q.2971:Call-Control-U Missing
+ * Q.2971:Call-Control-N 14/39
+ */
+static void
+u4n7_t301(struct call *c)
+{
+ VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T301 tick",
+ c->cref, c->mine ? "mine" : "his");
+
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_NO_RESP_ALERT);
+ clear_callD(c);
+}
+
+/*
+ * ALERTING received
+ *
+ * Q.2971:Call-Control-U 37/39 (U1)
+ * Q.2971:Call-Control-U 7/39 (U3)
+ * Q.2971:Call-Control-N 9/39 (N6)
+ * Q.2971:Call-Control-N 17/39 (N9)
+ *
+ * There are two errors in the user side SDL Annex A:
+ *
+ * - the resetted timers are swapped (T310 and T303)
+ *
+ * - for U1 we should go to C12, not C3 to start T301.
+ */
+static void
+unx_alerting(struct call *c, struct uni_msg *m, struct uni_all *u,
+ enum call_state new_state)
+{
+ struct uni_alerting *al = &u->u.alerting;
+ struct uniapi_alerting_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_alerting_indication, api);
+ if (ind == NULL) {
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ if (!IE_ISPRESENT(c->connid) && !IE_ISGOOD(al->connid))
+ uni_mandate_ie(c->uni, UNI_IE_CONNID);
+
+ /*
+ * Q.2971: L3MU_01_04 requests us to ignore the message if the
+ * EPREF is missing.
+ */
+ if (c->msg_setup.bearer.cfg == UNI_BEARER_MP &&
+ IE_ISPRESENT(c->msg_setup.epref)) {
+ if (!IE_ISPRESENT(al->epref))
+ uni_mandate_ie(c->uni, UNI_IE_EPREF); \
+
+ else if (IE_ISGOOD(al->epref) &&
+ (al->epref.flag != 1 ||
+ al->epref.epref != c->msg_setup.epref.epref)) {
+ IE_SETERROR(al->epref);
+ (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF,
+ al->epref.h.act, UNI_IERR_BAD);
+ }
+ }
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ case VFY_I:
+ uni_msg_destroy(api);
+ goto ignore;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ report:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), NULL, 0);
+ uni_msg_destroy(api);
+ goto ignore;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ if (c->type == CALL_ROOT && !IE_ISGOOD(al->epref))
+ goto report;
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), NULL, 0);
+ case VFY_OK:
+ break;
+ }
+
+ if (c->cstate == CALLST_U1 || c->cstate == CALLST_N6)
+ TIMER_STOP_CALL(c, t303);
+ else if (c->cstate == CALLST_U3 || c->cstate == CALLST_N9)
+ TIMER_STOP_CALL(c, t310);
+
+ if (IE_ISGOOD(al->connid))
+ c->connid = al->connid;
+
+ ind->alerting.hdr = u->u.hdr;
+ copy_msg_alerting(al, &ind->alerting);
+
+ if (c->type == CALL_LEAF || c->type == CALL_ROOT) {
+ uni_enq_party(TAILQ_FIRST(&c->parties), SIGP_ALERTING,
+ 0, NULL, NULL);
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_ALERTING_indication, 0, api);
+ } else {
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_ALERTING_indication, 0, api);
+ TIMER_START_CALL(c, t301, c->uni->timer301);
+ }
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+
+ set_call_state(c, new_state);
+}
+
+/*
+ * Proceeding.request from API
+ *
+ * Q.2971:Call-Control-U 12/39 (U6)
+ * Q.2971:Call-Control-N 6/39 (N1)
+ */
+static void
+u6n1_proceeding_request(struct call *c, struct uni_msg *m, uint32_t cookie,
+ enum call_state new_state)
+{
+ struct uni_all *msg;
+ struct uniapi_proceeding_request *arg =
+ uni_msg_rptr(m, struct uniapi_proceeding_request *);
+
+ if ((msg = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+
+ if (IE_ISGOOD(arg->call_proc.connid))
+ c->connid = arg->call_proc.connid;
+
+ msg->u.call_proc = arg->call_proc;
+ MK_MSG_ORIG(msg, UNI_CALL_PROC, c->cref, !c->mine);
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+
+ set_call_state(c, new_state);
+
+ uni_msg_destroy(m);
+
+ uniapi_call_error(c, UNIAPI_OK, cookie);
+}
+
+/*
+ * Alerting.request from API
+ *
+ * Q.2971:Call-Control-U 13/39 (U6)
+ * Q.2971:Call-Control-U 17/39 (U9)
+ * Q.2971:Call-Control-N 38/39 (N1)
+ * Q.2971:Call-Control-N 7/39 (N3)
+ */
+static void
+unx_alerting_request(struct call *c, struct uni_msg *m, uint32_t cookie,
+ enum call_state new_state)
+{
+ struct uni_all *msg;
+ struct uniapi_alerting_request *arg =
+ uni_msg_rptr(m, struct uniapi_alerting_request *);
+
+ if ((msg = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+
+ if (c->type == CALL_ROOT || c->type == CALL_LEAF) {
+ uni_enq_party(TAILQ_FIRST(&c->parties),
+ SIGP_ALERTING_request, cookie, NULL, NULL);
+ }
+
+ /*
+ * It's not really clear, what happens, if we send another
+ * connid in CALL_PROC and ALERTING
+ */
+ if (!IE_ISGOOD(c->connid) && IE_ISGOOD(arg->alerting.connid))
+ c->connid = arg->alerting.connid;
+
+ msg->u.alerting = arg->alerting;
+ MK_MSG_ORIG(msg, UNI_ALERTING, c->cref, !c->mine);
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+
+ set_call_state(c, new_state);
+
+ uni_msg_destroy(m);
+
+ uniapi_call_error(c, UNIAPI_OK, cookie);
+}
+
+
+/*
+ * Setup.response from API
+ *
+ * Q.2971:Call-Control-U 13/39 (U6)
+ * Q.2971:Call-Control-U 14/39 (U7)
+ * Q.2971:Call-Control-U 17/39 (U9)
+ * Q.2971:Call-Control-N 39/39 (N1)
+ * Q.2971:Call-Control-N 7/39 (N3)
+ * Q.2971:Call-Control-N 8/39 (N4)
+ */
+static void
+unx_setup_response(struct call *c, struct uni_msg *m, uint32_t cookie,
+ enum call_state new_state)
+{
+ struct uni_all *msg;
+ struct uniapi_setup_response *arg =
+ uni_msg_rptr(m, struct uniapi_setup_response *);
+ struct party *p;
+
+ if ((msg = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+
+ if (!IE_ISGOOD(c->connid) && IE_ISGOOD(arg->connect.connid))
+ c->connid = arg->connect.connid;
+
+ if (IE_ISGOOD(arg->connect.epref)) {
+ p = uni_find_partyx(c, arg->connect.epref.epref,
+ !arg->connect.epref.flag);
+ if (p == NULL) {
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie);
+ UNI_FREE(msg);
+ uni_msg_destroy(m);
+ return;
+ }
+ /* we need to remember that we have sent the CONNECT from this
+ * party because the CONNECT ACK must move only this party
+ * into P7 */
+ 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);
+ return;
+ }
+
+ /* inform the parties on the network side */
+ if (c->uni->proto == UNIPROTO_UNI40N && c->type == CALL_LEAF)
+ TAILQ_FOREACH(p, &c->parties, link)
+ uni_enq_party(p, SIGP_SETUP_response, 0, NULL, NULL);
+
+ msg->u.connect = arg->connect;
+ MK_MSG_ORIG(msg, UNI_CONNECT, c->cref, !c->mine);
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+
+ if (c->uni->proto == UNIPROTO_UNI40U)
+ TIMER_START_CALL(c, t313, c->uni->timer313);
+
+ set_call_state(c, new_state);
+
+ uni_msg_destroy(m);
+
+ uniapi_call_error(c, UNIAPI_OK, cookie);
+}
+
+/*
+ * Setup_complete.request
+ *
+ * Q.2971:Call-Control-N 15/39 (N8)
+ */
+static void
+n8_setup_compl_request(struct call *c, struct uni_msg *m, uint32_t cookie,
+ enum call_state new_state)
+{
+ struct uni_all *msg;
+ struct uniapi_setup_complete_request *arg =
+ uni_msg_rptr(m, struct uniapi_setup_complete_request *);
+ struct party *p;
+
+ if ((msg = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+
+ /* inform the parties on the network side */
+ if (c->uni->proto == UNIPROTO_UNI40N &&
+ (c->type == CALL_LEAF || c->type == CALL_ROOT)) {
+ TAILQ_FOREACH(p, &c->parties, link)
+ uni_enq_party(p, SIGP_SETUP_COMPL_request,
+ 0, NULL, NULL);
+ }
+
+ msg->u.connect_ack = arg->connect_ack;
+ MK_MSG_ORIG(msg, UNI_CONNECT_ACK, c->cref, !c->mine);
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+
+ set_call_state(c, new_state);
+
+ uni_msg_destroy(m);
+
+ uniapi_call_error(c, UNIAPI_OK, cookie);
+}
+
+/*
+ * CONNECT message
+ *
+ * Q.2971:Call-Control-U 7-8/39 (U3)
+ * Q.2971:Call-Control-U 11/39 (U4)
+ * Q.2971:Call-Control-U 37/39 (U1)
+ * Q.2971:Call-Control-N 9-10/39 (N6)
+ * Q.2971:Call-Control-N 14/39 (N7)
+ * Q.2971:Call-Control-N 17/39 (N9)
+ */
+static void
+unx_connect(struct call *c, struct uni_msg *m, struct uni_all *u,
+ enum call_state new_state)
+{
+ struct uni_connect *co = &u->u.connect;
+ struct uniapi_setup_confirm *conf;
+ struct uni_msg *api;
+ struct uni_all *ack;
+ struct party *p;
+
+ conf = ALLOC_API(struct uniapi_setup_confirm, api);
+ if (conf == NULL) {
+ ignore:
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+ return;
+ }
+ if ((ack = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(api);
+ goto ignore;
+ }
+
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ if (!IE_ISPRESENT(c->connid) && !IE_ISGOOD(co->connid))
+ uni_mandate_ie(c->uni, UNI_IE_CONNID);
+
+ /*
+ * Q.2971: L3MU_01_05 requires the epref to be present.
+ */
+ p = NULL;
+ if (c->msg_setup.bearer.cfg == UNI_BEARER_MP) {
+ if (IE_ISPRESENT(c->msg_setup.epref)) {
+ if (!IE_ISPRESENT(co->epref))
+ uni_mandate_ie(c->uni, UNI_IE_EPREF); \
+
+ if (IE_ISGOOD(co->epref) &&
+ co->epref.flag != 1) {
+ IE_SETERROR(co->epref);
+ (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF,
+ co->epref.h.act, UNI_IERR_BAD);
+ }
+ }
+
+ if (IE_ISGOOD(co->epref)) {
+ p = uni_find_party(c, &co->epref);
+ if (p == NULL) {
+ respond_drop_party_ack(c, &co->epref,
+ UNI_CAUSE_ENDP_INV);
+ uni_msg_destroy(api);
+ UNI_FREE(ack);
+ goto ignore;
+ }
+ }
+ }
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ /* FALLTHRU */
+ case VFY_I:
+ uni_msg_destroy(api);
+ UNI_FREE(ack);
+ goto ignore;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ report:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), NULL, 0);
+ uni_msg_destroy(api);
+ UNI_FREE(ack);
+ goto ignore;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ if (c->type == CALL_ROOT && !IE_ISGOOD(co->epref))
+ goto report;
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(new_state), NULL, 0);
+ /* FALLTHRU */
+ case VFY_OK:
+ break;
+ }
+
+ if (IE_ISGOOD(co->connid))
+ c->connid = co->connid;
+
+ if (c->cstate == CALLST_U1 || c->cstate == CALLST_N6)
+ TIMER_STOP_CALL(c, t303);
+ else if (c->cstate == CALLST_U3 || c->cstate == CALLST_N9)
+ TIMER_STOP_CALL(c, t310);
+ else if (c->cstate == CALLST_U4 || c->cstate == CALLST_N7) {
+ if(c->type == CALL_P2P)
+ TIMER_STOP_CALL(c, t301);
+ }
+
+ /*
+ * This is sent to the party only on the user side and only
+ * to the one party in the epref (L3MU_05_03).
+ */
+ if (c->uni->proto == UNIPROTO_UNI40U &&
+ (c->type == CALL_LEAF || c->type == CALL_ROOT))
+ uni_enq_party(p, SIGP_CONNECT, 0, NULL, NULL);
+
+ conf->connect.hdr = u->u.hdr;
+ copy_msg_connect(co, &conf->connect);
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_SETUP_confirm, 0, api);
+
+ if (c->uni->proto == UNIPROTO_UNI40U) {
+ /* this is left to the application on the network side */
+ MK_MSG_ORIG(ack, UNI_CONNECT_ACK, c->cref, !c->mine);
+ (void)uni_send_output(ack, c->uni);
+ UNI_FREE(ack);
+ }
+
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+
+ set_call_state(c, new_state);
+}
+
+/*
+ * T313 (Connect) timer tick.
+ *
+ * Q.2971:Call-Control-U 15/39
+ */
+static void
+u8_t313(struct call *c)
+{
+ VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T313 tick",
+ c->cref, c->mine ? "mine" : "his");
+
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(c->uni->cause, "313");
+ clear_callD(c);
+}
+
+/*
+ * CONNECT ACKNOWLEDGE message in U8
+ *
+ * Q.2971:Call-Control-U 15-16/39
+ */
+static void
+u8_connect_ack(struct call *c, struct uni_msg *m, struct uni_all *u,
+ enum call_state new_state)
+{
+ struct uniapi_setup_complete_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_setup_complete_indication, api);
+ if (ind == NULL) {
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ /* FALLTHRU */
+ case VFY_I:
+ uni_msg_destroy(api);
+ goto ignore;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), NULL, 0);
+ uni_msg_destroy(api);
+ goto ignore;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(new_state), NULL, 0);
+ /* FALLTHRU */
+ case VFY_OK:
+ break;
+ }
+
+ TIMER_STOP_CALL(c, t313);
+
+ if (c->type == CALL_LEAF) {
+ struct party *p;
+
+ TAILQ_FOREACH(p, &c->parties, link) {
+ if (p->flags & PARTY_CONNECT) {
+ uni_enq_party(p, SIGP_CONNECT_ACK,
+ 0, NULL, NULL);
+ break;
+ }
+ }
+ }
+
+ ind->connect_ack.hdr = u->u.hdr;
+ copy_msg_connect_ack(&u->u.connect_ack, &ind->connect_ack);
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_SETUP_COMPLETE_indication, 0, api);
+
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+
+ set_call_state(c, new_state);
+}
+
+/*
+ * CONNECT ACKNOWLEDGE message in N10
+ *
+ * Q.2971:Call-Control-N 18/39
+ */
+static void
+n10_connect_ack(struct call *c, struct uni_msg *m, struct uni_all *u)
+{
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ /* FALLTHRU */
+ case VFY_I:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), NULL, 0);
+ /* FALLTHRU */
+ case VFY_OK:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+}
+
+/*
+ * Release.response in U6 or U12.
+ *
+ * Q.2971:Call-Control-U 12/39 (U6)
+ * Q.2971:Call-Control-U 30/39 (U12)
+ * Q.2971:Call-Control-N 6/39 (N1)
+ * Q.2971:Call-Control-N 29/39 (N11)
+ */
+static void
+unx_release_response(struct call *c, struct uni_msg *m, uint32_t cookie)
+{
+ struct party *p;
+ struct uni_all *msg;
+ struct uniapi_release_response *arg =
+ uni_msg_rptr(m, struct uniapi_release_response *);
+
+ if ((msg = UNI_ALLOC()) == NULL) {
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(m);
+ return;
+ }
+
+ if (c->cstate == CALLST_U6 || c->cstate == CALLST_N1) {
+ if (c->type == CALL_ROOT || c->type == CALL_LEAF) {
+ TAILQ_FOREACH(p, &c->parties, link)
+ uni_enq_party(p, SIGP_RELEASE_response,
+ cookie, NULL, NULL);
+ }
+ }
+ msg->u.release_compl = arg->release_compl;
+ MK_MSG_ORIG(msg, UNI_RELEASE_COMPL, c->cref, !c->mine);
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+
+ uni_msg_destroy(m);
+
+ uniapi_call_error(c, UNIAPI_OK, cookie);
+
+ uni_destroy_call(c, 0);
+}
+
+/*
+ * Got a RELEASE COMPLETE in any state expect U0
+ *
+ * Q.2971:Call-Control-U 25/39
+ * Q.2971:Call-Control-N 26/39
+ *
+ * This is also called from the restart processes.
+ */
+void
+uni_release_compl(struct call *c, struct uni_all *u)
+{
+ struct uni_msg *api;
+ struct uniapi_release_confirm *conf;
+ struct party *p;
+ u_int i, j;
+
+ if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) == NULL)
+ return;
+
+ reset_all_timers(c);
+ if (c->type == CALL_ROOT || c->type == CALL_LEAF) {
+ TAILQ_FOREACH(p, &c->parties, link)
+ uni_enq_party(p, SIGP_RELEASE_COMPL, 0, NULL, NULL);
+ /* YYY optional call reoffering 10.3.3/10.3.4 */
+ }
+ conf->release.hdr = u->u.hdr;
+
+ for (i = j = 0; i < 2; i++)
+ if (IE_ISGOOD(u->u.release_compl.cause[i]))
+ conf->release.cause[j++] = u->u.release_compl.cause[i];
+ for (i = j = 0; i < UNI_NUM_IE_GIT; i++)
+ if (IE_ISGOOD(u->u.release_compl.git[i]))
+ conf->release.git[j++] = u->u.release_compl.git[i];
+ if (IE_ISGOOD(u->u.release_compl.uu))
+ conf->release.uu = u->u.release_compl.uu;
+ if (IE_ISGOOD(u->u.release_compl.crankback))
+ conf->release.crankback = u->u.release_compl.crankback;
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_confirm, 0, api);
+
+ uni_destroy_call(c, 0);
+}
+static void
+unx_release_compl(struct call *c, struct uni_msg *m, struct uni_all *u)
+{
+
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ (void)uni_verify(c->uni, u->u.hdr.act); /* no point :-) */
+
+ uni_release_compl(c, u);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * Got a RELEASE COMPLETE in any state expect U0 and U11
+ *
+ * Q.2971:Call-Control-U 25/39
+ * Q.2971:Call-Control-N 26/39
+ */
+static void
+unx_release(struct call *c, struct uni_msg *m, struct uni_all *u,
+ enum call_state new_state)
+{
+ struct uniapi_release_indication *ind;
+ struct uni_msg *api;
+
+ if ((ind = ALLOC_API(struct uniapi_release_indication, api)) == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ (void)uni_verify(c->uni, u->u.hdr.act); /* no point :-) */
+
+ reset_all_timers(c);
+ if (c->type == CALL_ROOT || c->type == CALL_LEAF) {
+ struct party *p;
+
+ TAILQ_FOREACH(p, &c->parties, link)
+ uni_enq_party(p, SIGP_RELEASE, 0, NULL, NULL);
+ /* YYY optional call reoffering 10.3.3/10.3.4 */
+ }
+ if (c->cstate != new_state) {
+ /*
+ * According to Q.2971 we should send a 2nd
+ * Release.indication.
+ * According to Q.2931 the recipte of a RELEASE in U12/N11
+ * is illegal.
+ * According to us make it legal, but don't send a 2nd
+ * indication.
+ */
+ ind->release.hdr = u->u.hdr;
+ copy_msg_release(&u->u.release, &ind->release);
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_indication, 0, api);
+ } else
+ uni_msg_destroy(api);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_call_state(c, new_state);
+}
+
+/*
+ * Got RELEASE in U11 or N12
+ *
+ * Q.2971:Call-Control-U 28/39
+ * Q.2971:Call-Control-N 30/39
+ */
+static void
+u11n12_release(struct call *c, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_release_confirm *conf;
+ struct uni_msg *api;
+
+ if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ (void)uni_verify(c->uni, u->u.hdr.act); /* no point :-) */
+
+ TIMER_STOP_CALL(c, t308);
+
+ conf->release.hdr = u->u.hdr;
+ copy_msg_release(&u->u.release, &conf->release);
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_confirm, 0, api);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ uni_destroy_call(c, 0);
+}
+
+/*
+ * NOTIFY message
+ *
+ * Q.2971:Call-Control-U 18/39
+ * Q.2971:Call-Control-N 19/39
+ */
+static void
+unx_notify(struct call *c, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_notify_indication *ind;
+ struct uni_msg *api;
+ struct party *p = NULL;
+
+ if ((ind = ALLOC_API(struct uniapi_notify_indication, api)) == NULL) {
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ MANDATE_IE(c->uni, u->u.notify.notify, UNI_IE_NOTIFY);
+
+ if (IE_ISGOOD(u->u.notify.epref)) {
+ if ((p = uni_find_party(c, &u->u.notify.epref)) == NULL) {
+ respond_drop_party_ack(c, &u->u.notify.epref,
+ UNI_CAUSE_ENDP_INV);
+ uni_msg_destroy(api);
+ goto ignore;
+ }
+ }
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_msg_destroy(api);
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ goto ignore;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), &u->u.notify.epref,
+ p ? p->state : 0);
+ /* FALLTHRU */
+ case VFY_I:
+ uni_msg_destroy(api);
+ goto ignore;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), &u->u.notify.epref,
+ p ? p->state : 0);
+ case VFY_OK:
+ /* FALLTHRU */
+ break;
+ }
+
+ ind->notify.hdr = u->u.hdr;
+ copy_msg_notify(&u->u.notify, &ind->notify);
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_NOTIFY_indication, 0, api);
+
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+}
+
+/*
+ * Notify.request from user
+ *
+ * Q.2971:Call-Control-U 18/39
+ * Q.2971:Call-Control-N 19/39
+ */
+static void
+unx_notify_request(struct call *c, struct uni_msg *m, uint32_t cookie)
+{
+ struct uni_all *msg;
+ struct uniapi_notify_request *arg =
+ uni_msg_rptr(m, struct uniapi_notify_request *);
+
+ if ((msg = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+
+ msg->u.notify = arg->notify;
+ MK_MSG_ORIG(msg, UNI_NOTIFY, c->cref, !c->mine);
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+
+ uni_msg_destroy(m);
+
+ uniapi_call_error(c, UNIAPI_OK, cookie);
+}
+
+/**********************************************************************/
+
+/*
+ * Release.request from API in any state except U11, U12, N11, N12
+ *
+ * Q.2971:Call-Control-U 27/39
+ * Q.2971:Call-Control-N 28/39
+ */
+static void
+unx_release_request(struct call *c, struct uni_msg *m, uint32_t cookie,
+ enum call_state new_state)
+{
+ struct uni_all *msg;
+ struct uniapi_release_request *arg =
+ uni_msg_rptr(m, struct uniapi_release_request *);
+ struct party *p;
+
+ if ((msg = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(m);
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+
+ reset_all_timers(c);
+
+ if (c->type == CALL_LEAF || c->type == CALL_ROOT) {
+ TAILQ_FOREACH(p, &c->parties, link) {
+ uni_enq_party(p, SIGP_RELEASE_request, cookie,
+ NULL, NULL);
+ }
+ }
+
+ c->msg_release = arg->release;
+ if (!IE_ISPRESENT(c->msg_release.cause[0]) &&
+ !IE_ISPRESENT(c->msg_release.cause[1]))
+ MK_IE_CAUSE(c->msg_release.cause[0], UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_UNSPEC);
+
+ msg->u.release = c->msg_release;
+ MK_MSG_ORIG(msg, UNI_RELEASE, c->cref, !c->mine);
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+
+ TIMER_START_CALL(c, t308, c->uni->timer308);
+ c->cnt308 = 0;
+
+ set_call_state(c, new_state);
+
+ uni_msg_destroy(m);
+
+ uniapi_call_error(c, UNIAPI_OK, cookie);
+}
+
+/*
+ * Message with unknown EPREF - send a drop party according to 9.5.3.2.3a)
+ */
+static void
+respond_drop_party_ack(struct call *c, struct uni_ie_epref *epref,
+ u_int cause)
+{
+ struct uni_all *msg;
+
+ if ((msg = UNI_ALLOC()) == NULL)
+ return;
+
+ MK_MSG_ORIG(msg, UNI_DROP_PARTY_ACK, c->cref, !c->mine);
+ MK_IE_EPREF(msg->u.drop_party_ack.epref, epref->epref, !epref->flag);
+ MK_IE_CAUSE(msg->u.drop_party_ack.cause, UNI_CAUSE_LOC_USER, cause);
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+}
+
+/*
+ * T308 (RELEASE) timer
+ *
+ * Q.2971:Call-Control-U 28/39
+ * Q.2971:Call-Control-N 30/39
+ */
+static void
+u11n12_t308(struct call *c)
+{
+ struct uni_all *msg;
+ struct uni_msg *api;
+ struct uniapi_release_confirm *conf;
+
+ VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T308 tick %d",
+ c->cref, c->mine ? "mine" : "his", c->cnt308 + 1);
+
+ if (++c->cnt308 < c->uni->init308) {
+ if ((msg = UNI_ALLOC()) != NULL) {
+ msg->u.release = c->msg_release;
+ MK_MSG_ORIG(msg, UNI_RELEASE, c->cref, !c->mine);
+ if (!IE_ISPRESENT(msg->u.release.cause[1])) {
+ MK_IE_CAUSE(msg->u.release.cause[1],
+ UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(msg->u.release.cause[1], "308");
+ }
+ (void)uni_send_output(msg, c->uni);
+ UNI_FREE(msg);
+ }
+ TIMER_START_CALL(c, t308, c->uni->timer308);
+ return;
+ }
+
+ /*
+ * Send indication to API
+ */
+ if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) {
+ conf->release.hdr.cref.cref = c->cref;
+ conf->release.hdr.cref.flag = c->mine;
+ conf->release.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(conf->release.cause[0], "308");
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_confirm, 0, api);
+ }
+
+ uni_destroy_call(c, 0);
+}
+/**********************************************************************/
+
+/*
+ * STATUS in U11/U12
+ *
+ * Q.2971:Call-Control-U 29/39 (U11)
+ * Q.2971:Call-Control-U 30/39 (U12)
+ * Q.2971:Call-Control-N 29/39 (N11)
+ * Q.2971:Call-Control-N 31/39 (N12)
+ */
+static void
+un11un12_status(struct call *c, struct uni_msg *m, struct uni_all *u)
+{
+ enum call_state ns;
+ struct uniapi_release_confirm *conf;
+ struct uni_msg *api;
+ struct party *p;
+ struct uniapi_status_indication *stat;
+
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ MANDATE_IE(c->uni, u->u.status.callstate, UNI_IE_CALLSTATE);
+ MANDATE_IE(c->uni, u->u.status.cause, UNI_IE_CAUSE);
+
+ ns = c->cstate;
+ if (IE_ISGOOD(u->u.status.callstate) &&
+ u->u.status.callstate.state == UNI_CALLSTATE_U0)
+ ns = CALLST_NULL;
+
+ p = NULL;
+ if (IE_ISGOOD(u->u.status.epref))
+ p = uni_find_party(c, &u->u.status.epref);
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(ns), &u->u.status.epref,
+ p ? p->state : UNI_EPSTATE_NULL);
+ case VFY_I:
+ case VFY_OK:
+ break;
+ }
+
+ if (ns == c->cstate) {
+ /*
+ * Inform API
+ */
+ stat = ALLOC_API(struct uniapi_status_indication, api);
+ if (stat != NULL) {
+ stat->cref = u->u.hdr.cref;
+ stat->my_state = map_callstate(c->cstate);
+ stat->his_state = u->u.status.callstate;
+ stat->his_cause = u->u.status.cause;
+ stat->epref = u->u.status.epref;
+ stat->epstate = u->u.status.epstate;
+ stat->my_cause = 0;
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_STATUS_indication, 0, api);
+ }
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ return;
+ }
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ /*
+ * Send indication to API
+ */
+ if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) {
+ conf->release.hdr.cref.cref = c->cref;
+ conf->release.hdr.cref.flag = c->mine;
+ conf->release.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MSG_INCOMP);
+ ADD_CAUSE_MTYPE(conf->release.cause[0], UNI_STATUS);
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_confirm, 0, api);
+ }
+
+ uni_destroy_call(c, 0);
+}
+
+static int
+status_enq_filter(struct sig *sig, void *arg)
+{
+ return (sig->type == SIG_CALL &&
+ (struct call *)arg == sig->call &&
+ sig->sig == SIGC_SEND_STATUS_ENQ);
+}
+
+/*
+ * STATUS in any state except U0/U11/U12 N0/N11/N12
+ *
+ * Q.2971:Call-Control-U 32/39
+ * Q.2971:Call-Control-N 33/39
+ */
+static void
+unx_status(struct call *c, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_status_indication *stat;
+ struct uniapi_release_confirm *conf;
+ enum call_state ns;
+ struct uni_msg *api;
+ struct party *p;
+
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ MANDATE_IE(c->uni, u->u.status.callstate, UNI_IE_CALLSTATE);
+ MANDATE_IE(c->uni, u->u.status.cause, UNI_IE_CAUSE);
+
+ ns = c->cstate;
+ if (IE_ISGOOD(u->u.status.callstate))
+ ns = state_compat(c, u->u.status.callstate.state);
+
+ p = NULL;
+ if (IE_ISGOOD(u->u.status.epref)) {
+ p = uni_find_party(c, &u->u.status.epref);
+ MANDATE_IE(c->uni, u->u.status.epstate, UNI_IE_EPSTATE);
+ }
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(ns), &u->u.notify.epref,
+ p ? p->state : UNI_EPSTATE_NULL);
+ /* FALLTHRU */
+ case VFY_I:
+ case VFY_OK:
+ break;
+ }
+
+ if (u->u.status.callstate.state == UNI_CALLSTATE_U0) {
+ /* release_complete */
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ if (c->type == CALL_LEAF || c->type == CALL_ROOT) {
+ TAILQ_FOREACH(p, &c->parties, link)
+ uni_enq_party(p, SIGP_RELEASE_COMPL,
+ 0, NULL, NULL);
+ }
+ /*
+ * Send indication to API
+ */
+ conf = ALLOC_API(struct uniapi_release_confirm, api);
+ if (conf != NULL) {
+ conf->release.hdr.cref.cref = c->cref;
+ conf->release.hdr.cref.flag = c->mine;
+ conf->release.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MSG_INCOMP);
+ ADD_CAUSE_MTYPE(conf->release.cause[0], UNI_STATUS);
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_confirm, 0, api);
+ }
+ uni_destroy_call(c, 0);
+ return;
+ }
+
+ if (IE_ISGOOD(u->u.status.cause) &&
+ u->u.status.cause.cause == UNI_CAUSE_STATUS) {
+ c->se_active = 0;
+ TIMER_STOP_CALL(c, t322);
+ uni_undel(c->uni, status_enq_filter, c);
+ }
+
+ /*
+ * Inform API
+ */
+ if ((stat = ALLOC_API(struct uniapi_status_indication, api)) != NULL) {
+ stat->cref = u->u.hdr.cref;
+ stat->my_state = map_callstate(c->cstate);
+ stat->his_state = u->u.status.callstate;
+ stat->his_cause = u->u.status.cause;
+ stat->epref = u->u.status.epref;
+ stat->epstate = u->u.status.epstate;
+ }
+
+ if (ns == c->cstate) {
+ /* compatible or recovered */
+ if (p != NULL)
+ uni_enq_party(p, SIGP_STATUS, 0, m, u);
+ else {
+ if (IE_ISGOOD(u->u.status.epref) &&
+ (!IE_ISGOOD(u->u.status.epstate) ||
+ u->u.status.epstate.state != UNI_EPSTATE_NULL))
+ respond_drop_party_ack(c, &u->u.status.epref,
+ UNI_CAUSE_MSG_INCOMP);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ }
+ if (stat != NULL) {
+ stat->my_cause = 0;
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_STATUS_indication, 0, api);
+ }
+
+ return;
+ }
+
+ /* incompatible */
+ if (stat != NULL) {
+ stat->my_cause = UNI_CAUSE_MSG_INCOMP;
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_STATUS_indication, 0, api);
+ }
+
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_MSG_INCOMP);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ clear_callD(c);
+}
+
+/*
+ * Enquiry peer status
+ *
+ * Q.2971:Call-Control-U 31/39
+ * Q.2971:Call-Control-N 32/39
+ */
+static void
+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 *);
+ struct party *p;
+ struct uni_all *stat;
+
+ if (c->se_active) {
+ /* This case is not handled in the SDLs */
+ uniapi_call_error(c, UNIAPI_ERROR_BUSY, cookie);
+ uni_msg_destroy(msg);
+ return;
+ }
+ if ((c->type == CALL_ROOT || c->type == CALL_LEAF) &&
+ IE_ISGOOD(arg->epref)) {
+ if ((p = uni_find_partyx(c, arg->epref.epref, !arg->epref.flag))
+ == NULL) {
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie);
+ uni_msg_destroy(msg);
+ return;
+ }
+ uni_msg_destroy(msg);
+ uni_enq_party(p, SIGP_STATUS_ENQUIRY_request, cookie,
+ NULL, NULL);
+ return;
+ }
+ if ((stat = UNI_ALLOC()) == NULL) {
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(msg);
+ return;
+ }
+ memset(&c->stat_epref, 0, sizeof(c->stat_epref));
+ MK_MSG_ORIG(stat, UNI_STATUS_ENQ, c->cref, !c->mine);
+ (void)uni_send_output(stat, c->uni);
+ UNI_FREE(stat);
+
+ TIMER_START_CALL(c, t322, c->uni->timer322);
+ c->cnt322 = 0;
+ c->se_active = 1;
+
+ uniapi_call_error(c, UNIAPI_OK, cookie);
+}
+
+/*
+ * T322 tick
+ *
+ * Q.2971:Call-Control-U 34/39
+ * Q.2971:Call-Control-N 35/39
+ */
+static void
+unx_t322(struct call *c)
+{
+ struct uni_all *stat;
+
+ VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T322 tick %d",
+ c->cref, c->mine ? "mine" : "his", c->cnt322 + 1);
+
+ if (++c->cnt322 < c->uni->init322) {
+ if ((stat = UNI_ALLOC()) != NULL) {
+ MK_MSG_ORIG(stat, UNI_STATUS_ENQ, c->cref, !c->mine);
+ stat->u.status_enq.epref = c->stat_epref;
+ (void)uni_send_output(stat, c->uni);
+ UNI_FREE(stat);
+ }
+ TIMER_START_CALL(c, t322, c->uni->timer322);
+ return;
+ }
+ c->se_active = 0;
+
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(c->uni->cause, "322");
+
+ clear_callD(c);
+}
+
+/*
+ * STATUS ENQUIRY message
+ *
+ * Q.2971:Call-Control-U 31/39
+ * Q.2971:Call-Control-N 32/39
+ */
+static void
+unx_status_enq(struct call *c, struct uni_msg *m, struct uni_all *u)
+{
+ struct party *p = NULL;
+ u_int epref, flag;
+
+ /*
+ * Analyze message
+ */
+ (void)uni_decode_body(m, u, &c->uni->cx);
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ case VFY_RAP:
+ case VFY_RAPU:
+ case VFY_I:
+ case VFY_OK:
+ break;
+ }
+
+ uni_msg_destroy(m);
+
+ if ((c->type == CALL_ROOT || c->type == CALL_LEAF) &&
+ IE_ISGOOD(u->u.status_enq.epref)) {
+ p = uni_find_party(c, &u->u.status_enq.epref);
+
+ epref = u->u.status_enq.epref.epref;
+ flag = u->u.status_enq.epref.flag;
+ memset(u, 0, sizeof(*u));
+ MK_IE_EPREF(u->u.status.epref, epref, !flag);
+
+ if (p != NULL)
+ MK_IE_EPSTATE(u->u.status.epstate, p->state);
+ else
+ MK_IE_EPSTATE(u->u.status.epstate, UNI_EPSTATE_NULL);
+ } else
+ memset(u, 0, sizeof(*u));
+
+
+ MK_MSG_ORIG(u, UNI_STATUS, c->cref, !c->mine);
+ MK_IE_CALLSTATE(u->u.status.callstate, map_callstate(c->cstate));
+ MK_IE_CAUSE(u->u.status.cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_STATUS);
+ (void)uni_send_output(u, c->uni);
+ UNI_FREE(u);
+}
+
+/**********************************************************************/
+
+/*
+ * Link-release.indication from SAAL in state U10 or N10.
+ *
+ * Q.2971:Call-Control-U 19/39
+ * Q.2971:Call-Control-N 20/39
+ */
+static void
+un10_link_release_indication(struct call *c)
+{
+ struct party *p;
+
+ if (c->type == CALL_LEAF || c->type == CALL_ROOT)
+ TAILQ_FOREACH(p, &c->parties, link) {
+ if (p->state != UNI_EPSTATE_ACTIVE)
+ uni_enq_party(p, SIGP_RELEASE_COMPL,
+ 0, NULL, NULL);
+ }
+
+ uni_enq_coord(c->uni, SIGO_LINK_ESTABLISH_request, 0, NULL);
+}
+
+/*
+ * Link-release.indication from SAAL in all state except U10 and N10.
+ *
+ * Q.2971:Call-Control-U 36/39
+ * Q.2971:Call-Control-N 37/39
+ */
+static void
+unx_link_release_indication(struct call *c)
+{
+ struct uniapi_release_confirm *conf;
+ struct uni_msg *api;
+ struct party *p;
+
+ if (c->type == CALL_LEAF || c->type == CALL_ROOT)
+ TAILQ_FOREACH(p, &c->parties, link)
+ uni_enq_party(p, SIGP_RELEASE_COMPL, 0, NULL, NULL);
+
+ if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) {
+ conf->release.hdr.cref.cref = c->cref;
+ conf->release.hdr.cref.flag = c->mine;
+ conf->release.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_DST_OOO);
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_confirm, 0, api);
+ }
+
+ uni_destroy_call(c, 0);
+}
+
+/*
+ * Failed to establish SAAL link. Can happen only in U10 or N10.
+ *
+ * Q.2971:Call-Control-U 19/39
+ * Q.2971:Call-Control-N 20/39
+ */
+static void
+un10_link_establish_error_indication(struct call *c)
+{
+ struct party *p;
+ struct uni_msg *api;
+ struct uniapi_release_confirm *conf;
+
+ if (c->type == CALL_LEAF || c->type == CALL_ROOT)
+ TAILQ_FOREACH(p, &c->parties, link)
+ uni_enq_party(p, SIGP_RELEASE_COMPL, 0, NULL, NULL);
+
+ if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) {
+ conf->release.hdr.cref.cref = c->cref;
+ conf->release.hdr.cref.flag = c->mine;
+ conf->release.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_DST_OOO);
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_RELEASE_confirm, 0, api);
+ }
+
+ uni_destroy_call(c, 0);
+}
+
+/*
+ * Issue a STATUS ENQUIRY of we are not busy
+ *
+ * Q.2971: Call-Control-U: 34/39
+ * Q.2971: Call-Control-N: 34/39
+ */
+static void
+call_se(struct call *c)
+{
+ struct uni_all *stat;
+
+ c->cnt322 = 0;
+ if (c->se_active)
+ return;
+
+ memset(&c->stat_epref, 0, sizeof(c->stat_epref));
+ if ((stat = UNI_ALLOC()) != NULL) {
+ MK_MSG_ORIG(stat, UNI_STATUS_ENQ, c->cref, !c->mine);
+ (void)uni_send_output(stat, c->uni);
+ UNI_FREE(stat);
+ }
+
+ TIMER_START_CALL(c, t322, c->uni->timer322);
+ c->se_active = 1;
+}
+
+/*
+ * Link-establish.indication in U10
+ *
+ * Q.2971:Call-Control-U 19-20/39
+ * Q.2971:Call-Control-N 20-22/39
+ */
+static void
+un10_link_establish_indication(struct call *c)
+{
+ int act = 0;
+ struct party *p;
+
+ if (c->type == CALL_ROOT || c->type == CALL_LEAF) {
+ TAILQ_FOREACH(p, &c->parties, link)
+ if (p->state == UNI_EPSTATE_ACTIVE) {
+ act = 1;
+ uni_enq_party(p, SIGP_STATUS_ENQUIRY_request,
+ 0, NULL, NULL);
+ }
+ if (act)
+ return;
+ }
+ call_se(c);
+}
+
+/*
+ * Link-establish.indication in NOT U10/U11/U12 N10/N11/N12
+ *
+ * Q.2971:Call-Control-U 36/39
+ * Q.2971:Call-Control-N 37/39
+ */
+static void
+unx_link_establish_indication(struct call *c)
+{
+ call_se(c);
+}
+
+/*
+ * Link-establish.confirm in U10 or N10
+ *
+ * Q.2971:Call-Control-U 19/39
+ * Q.2971:Call-Control-N 20/39
+ */
+static void
+un10_link_establish_confirm(struct call *c)
+{
+ struct party *p;
+
+ if (c->type == CALL_ROOT || c->type == CALL_LEAF) {
+ TAILQ_FOREACH(p, &c->parties, link)
+ uni_enq_party(p, SIGP_STATUS_ENQUIRY_request,
+ 0, NULL, NULL);
+ return;
+ }
+
+ call_se(c);
+}
+
+/*
+ * STATUS ENQ from party
+ *
+ * Q.2971:Call-Control-U 21/39
+ * Q.2971:Call-Control-U 25/39
+ */
+static void
+unx_send_party_status_enq(struct call *c, struct uni_all *u)
+{
+ if (c->se_active) {
+ uni_delenq_sig(c->uni, SIG_CALL, c, NULL,
+ SIGC_SEND_STATUS_ENQ, 0, NULL, u);
+ return;
+ }
+
+ c->stat_epref = u->u.status_enq.epref;
+ (void)uni_send_output(u, c->uni);
+ UNI_FREE(u);
+
+ TIMER_START_CALL(c, t322, c->uni->timer322);
+ c->se_active = 1;
+}
+
+/**********************************************************************/
+
+static void
+make_drop_cause(struct call *c, struct uni_ie_cause *cause)
+{
+
+ if (!IE_ISGOOD(*cause)) {
+ /* 9.5.7.1 paragraph 2 */
+ if (IE_ISPRESENT(*cause))
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_INV);
+ else
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MANDAT);
+ c->uni->cause.u.ie.len = 1;
+ c->uni->cause.u.ie.ie[0] = UNI_IE_CAUSE;
+ c->uni->cause.h.present |= UNI_CAUSE_IE_P;
+
+ } else if (!IE_ISGOOD(c->uni->cause))
+ c->uni->cause = *cause;
+}
+
+/*
+ * Drop-party.indication from Party-Control in any state.
+ *
+ * Q.2971:Call-Control-U 23/39
+ */
+static void
+ux_drop_party_indication(struct call *c, struct uni_msg *api)
+{
+ struct uniapi_drop_party_indication *drop =
+ uni_msg_rptr(api, struct uniapi_drop_party_indication *);
+
+ if (uni_party_act_count(c, 2) == 0) {
+ if (c->cstate != CALLST_U11) {
+ make_drop_cause(c, &drop->drop.cause);
+ clear_callD(c);
+ }
+ uni_msg_destroy(api);
+ return;
+ }
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_DROP_PARTY_indication, 0, api);
+}
+
+/*
+ * Drop-party.indication from Party-Control in any state.
+ *
+ * Q.2971:Call-Control-N 23/39
+ */
+static void
+nx_drop_party_indication(struct call *c, struct uni_msg *api)
+{
+ struct uniapi_drop_party_indication *drop =
+ uni_msg_rptr(api, struct uniapi_drop_party_indication *);
+
+ if (uni_party_act_count(c, 0) == 0) {
+ if (uni_party_act_count(c, 1) == 0) {
+ if (c->cstate != CALLST_U11) {
+ make_drop_cause(c, &drop->drop.cause);
+ clear_callD(c);
+ }
+ uni_msg_destroy(api);
+ } else {
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_DROP_PARTY_indication, 0, api);
+ set_call_state(c, CALLST_N7);
+ }
+ } else {
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_DROP_PARTY_indication, 0, api);
+ }
+}
+
+/*
+ * Drop-party-ack.indication from Party-Control in any state.
+ *
+ * Q.2971:Call-Control-U 23/39
+ */
+static void
+ux_drop_party_ack_indication(struct call *c, struct uni_msg *api)
+{
+ struct uniapi_drop_party_ack_indication *drop =
+ uni_msg_rptr(api, struct uniapi_drop_party_ack_indication *);
+
+ if (uni_party_act_count(c, 2) == 0) {
+ if (c->cstate != CALLST_U11) {
+ make_drop_cause(c, &drop->drop.cause);
+ clear_callD(c);
+ }
+ uni_msg_destroy(api);
+ return;
+ }
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_DROP_PARTY_ACK_indication, 0, api);
+}
+
+/*
+ * Drop-party-ack.indication from Party-Control in any state.
+ *
+ * Q.2971:Call-Control-N 23/39
+ */
+static void
+nx_drop_party_ack_indication(struct call *c, struct uni_msg *api)
+{
+ struct uniapi_drop_party_ack_indication *drop =
+ uni_msg_rptr(api, struct uniapi_drop_party_ack_indication *);
+
+ if (uni_party_act_count(c, 0) == 0) {
+ if (uni_party_act_count(c, 1) == 0) {
+ if (c->cstate != CALLST_U11) {
+ make_drop_cause(c, &drop->drop.cause);
+ clear_callD(c);
+ }
+ uni_msg_destroy(api);
+ } else {
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_DROP_PARTY_ACK_indication, 0, api);
+ set_call_state(c, CALLST_N7);
+ }
+ } else {
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_DROP_PARTY_ACK_indication, 0, api);
+ }
+}
+
+/*
+ * Add-party-rej.indication from Party-Control in any state.
+ *
+ * Q.2971:Call-Control-U 23/39
+ */
+static void
+ux_add_party_rej_indication(struct call *c, struct uni_msg *api)
+{
+ struct uniapi_add_party_rej_indication *rej =
+ uni_msg_rptr(api, struct uniapi_add_party_rej_indication *);
+
+ if (uni_party_act_count(c, 2) == 0) {
+ if (c->cstate != CALLST_U11) {
+ make_drop_cause(c, &rej->rej.cause);
+ clear_callD(c);
+ }
+ uni_msg_destroy(api);
+ return;
+ }
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_ADD_PARTY_REJ_indication, 0, api);
+}
+
+/*
+ * Add-party-rej.indication from Party-Control in any state.
+ *
+ * Q.2971:Call-Control-N 23/39
+ */
+static void
+nx_add_party_rej_indication(struct call *c, struct uni_msg *api)
+{
+ struct uniapi_add_party_rej_indication *rej =
+ uni_msg_rptr(api, struct uniapi_add_party_rej_indication *);
+
+ if (uni_party_act_count(c, 0) == 0) {
+ if (uni_party_act_count(c, 1) == 0) {
+ if (c->cstate != CALLST_U11) {
+ make_drop_cause(c, &rej->rej.cause);
+ clear_callD(c);
+ }
+ uni_msg_destroy(api);
+ } else {
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_ADD_PARTY_REJ_indication, 0, api);
+ set_call_state(c, CALLST_N7);
+ }
+ } else {
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_ADD_PARTY_REJ_indication, 0, api);
+ }
+}
+
+/*
+ * Add-party.request from API in U4 or U10
+ *
+ * Q.2971:Call-Control-U 9-10/39 (U4)
+ * Q.2971:Call-Control-U 21/39 (U10)
+ * Q.2971:Call-Control-N 12/39 (N7)
+ * Q.2971:Call-Control-N 22/39 (N10)
+ */
+static void
+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 *);
+ struct party *p;
+
+ if (IE_ISGOOD(add->add.epref)) {
+ if (add->add.epref.flag != 0) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+ p = uni_find_partyx(c, add->add.epref.epref, 1);
+ if (p != NULL) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_EPREF_INUSE, cookie);
+ return;
+ }
+ } else if (!IE_ISPRESENT(add->add.epref)) {
+ allocate_epref(c, &add->add.epref);
+ if (!IE_ISPRESENT(add->add.epref)) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_EPREF_INUSE, cookie);
+ return;
+ }
+ } else {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+
+ if ((p = uni_create_partyx(c, add->add.epref.epref, 1, cookie)) == NULL) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+ uni_enq_party(p, SIGP_ADD_PARTY_request, cookie, msg, NULL);
+}
+
+/*
+ * Add-party-ack.request from API in U10/N10
+ *
+ * Q.2971:Call-Control-U 21/39
+ * Q.2971:Call-Control-N 22/39
+ */
+static void
+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 *);
+ struct party *p;
+
+ if (!IE_ISGOOD(ack->ack.epref)) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+ if (ack->ack.epref.flag != 1) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+ if ((p = uni_find_partyx(c, ack->ack.epref.epref, 0)) == NULL) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie);
+ return;
+ }
+
+ uni_enq_party(p, SIGP_ADD_PARTY_ACK_request, cookie, msg, NULL);
+}
+
+/*
+ * Party-alerting.request from API in U7/U8/U10
+ *
+ * Q.2971:Call-Control-U 14/39 U7
+ * Q.2971:Call-Control-U 15/39 U8
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-N 8/39 N4
+ * Q.2971:Call-Control-N 22/39 N10
+ */
+static void
+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 *);
+ struct party *p;
+
+ if (!IE_ISGOOD(alert->alert.epref)) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+ if (alert->alert.epref.flag != 1) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+ if ((p = uni_find_partyx(c, alert->alert.epref.epref, 0)) == NULL) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie);
+ return;
+ }
+
+ uni_enq_party(p, SIGP_PARTY_ALERTING_request, cookie, msg, NULL);
+}
+
+/*
+ * Add-party-rej.request from API in U7/U8/U10/N4/N10
+ *
+ * Q.2971:Call-Control-U 14/39 U7
+ * Q.2971:Call-Control-U 15/39 U8
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-N 8/39 N4
+ * Q.2971:Call-Control-N 22/39 N10
+ */
+static void
+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 *);
+ struct party *p;
+
+ if (!IE_ISGOOD(rej->rej.epref)) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+ if (rej->rej.epref.flag != 1) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+ if ((p = uni_find_partyx(c, rej->rej.epref.epref, 0)) == NULL) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie);
+ return;
+ }
+
+ uni_enq_party(p, SIGP_ADD_PARTY_REJ_request, cookie, msg, NULL);
+}
+
+/*
+ * Drop-party.request from API in U1-U10
+ *
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-U 26/39 U1-U9
+ * Q.2971:Call-Control-N 22/39 N10
+ * Q.2971:Call-Control-N 27/39 N1-N9
+ */
+static void
+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 *);
+ struct party *p;
+
+ if (!IE_ISGOOD(drop->drop.epref)) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+ if ((p = uni_find_partyx(c, drop->drop.epref.epref, !drop->drop.epref.flag)) == NULL) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie);
+ return;
+ }
+
+ uni_enq_party(p, SIGP_DROP_PARTY_request, cookie, msg, NULL);
+}
+
+/*
+ * Drop-party-ack.request from API in U1-U10
+ *
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-U 26/39 U1-U9
+ * Q.2971:Call-Control-N 22/39 N10
+ * Q.2971:Call-Control-N 27/39 N1-N9
+ */
+static void
+unx_drop_party_ack_request(struct call *c, struct uni_msg *msg,
+ uint32_t cookie)
+{
+ struct uniapi_drop_party_ack_request *ack =
+ uni_msg_rptr(msg, struct uniapi_drop_party_ack_request *);
+ struct party *p;
+
+ if (!IE_ISGOOD(ack->ack.epref)) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie);
+ return;
+ }
+ if ((p = uni_find_partyx(c, ack->ack.epref.epref, !ack->ack.epref.flag)) == NULL) {
+ uni_msg_destroy(msg);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie);
+ return;
+ }
+
+ uni_enq_party(p, SIGP_DROP_PARTY_ACK_request, cookie, msg, NULL);
+}
+
+/*
+ * ADD PARTY in U7/U8/U10
+ *
+ * Q.2971:Call-Control-U 14/39 U7
+ * Q.2971:Call-Control-U 15/39 U8
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-N 8/39 N4
+ * 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,
+ int legal)
+{
+ struct uni_all *resp;
+ struct uni_ierr *e1;
+ struct party *p = NULL;
+ enum verify vfy;
+
+ uni_mandate_epref(c->uni, &u->u.add_party.epref);
+ MANDATE_IE(c->uni, u->u.add_party.called, UNI_IE_CALLED);
+
+ /*
+ * Do part of the verify handish: according to 9.5.7.2 we must send
+ * an ADD_PARTY_REJ if mandatory IEs are bad or missing instead of
+ * clearing the call. But we must send a STATUS, if it is the EPREF!
+ */
+ if (IE_ISGOOD(u->u.add_party.epref)) {
+ c->uni->cause.u.ie.len = 0;
+ FOREACH_ERR(e1, c->uni) {
+ if (e1->err == UNI_IERR_MIS) {
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MANDAT);
+ goto rej;
+ }
+ }
+ FOREACH_ERR(e1, c->uni) {
+ if (e1->man && e1->ie != UNI_IE_EPREF &&
+ e1->act == UNI_IEACT_DEFAULT) {
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_INV);
+ rej:
+ uni_vfy_collect_ies(c->uni);
+ if ((resp = UNI_ALLOC()) != NULL) {
+ MK_MSG_RESP(resp, UNI_ADD_PARTY_REJ,
+ &u->u.hdr.cref);
+ MK_IE_EPREF(resp->u.add_party_rej.epref,
+ u->u.add_party.epref.epref,
+ !u->u.add_party.epref.flag);
+ resp->u.add_party_rej.cause =
+ c->uni->cause;
+
+ unx_send_add_party_rej(c, resp);
+ }
+ goto ignore;
+ }
+ }
+ p = uni_find_partyx(c, u->u.add_party.epref.epref,
+ u->u.add_party.epref.flag);
+ }
+
+ vfy = uni_verify(c->uni, u->u.hdr.act);
+
+ switch (vfy) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ goto ignore;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), &u->u.add_party.epref,
+ p ? p->state : UNI_EPSTATE_NULL);
+ /* FALLTHRU */
+ case VFY_I:
+ goto ignore;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), &u->u.add_party.epref,
+ UNI_EPSTATE_ADD_RCVD);
+ case VFY_OK:
+ /* FALLTHRU */
+ break;
+ }
+ if (!legal) {
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &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);
+ (void)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) {
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_INV);
+
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), NULL, 0);
+ }
+ goto ignore;
+ }
+
+
+ if (p == NULL && (p = uni_create_party(c, &u->u.add_party.epref))
+ == NULL)
+ goto ignore;
+
+ uni_enq_party(p, SIGP_ADD_PARTY, 0, m, u);
+ return;
+
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * ADD PARTY ACKNOWLEDGE
+ *
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-N 15/39 N8
+ * Q.2971:Call-Control-N 22/39 N10
+ */
+static void
+un10n8_add_party_ack(struct call *c, struct uni_msg *m, struct uni_all *u,
+ int legal)
+{
+ struct party *p = NULL;
+
+ if (IE_ISGOOD(u->u.add_party_ack.epref)) {
+ if (u->u.add_party_ack.epref.flag == 0) {
+ IE_SETERROR(u->u.add_party_ack.epref);
+ (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF,
+ u->u.add_party_ack.epref.h.act, UNI_IERR_BAD);
+ } else {
+ p = uni_find_partyx(c, u->u.add_party_ack.epref.epref, 1);
+ if (p == NULL) {
+ respond_drop_party_ack(c,
+ &u->u.add_party_ack.epref,
+ UNI_CAUSE_ENDP_INV);
+ goto ignore;
+ }
+ }
+ }
+ uni_mandate_epref(c->uni, &u->u.add_party_ack.epref);
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ goto ignore;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ report:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), &u->u.add_party_ack.epref,
+ p ? p->state : UNI_EPSTATE_NULL);
+ case VFY_I:
+ goto ignore;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), &u->u.add_party_ack.epref,
+ p ? UNI_EPSTATE_ACTIVE : UNI_EPSTATE_NULL);
+ if (!IE_ISGOOD(u->u.party_alerting.epref))
+ /* See below */
+ goto ignore;
+ break;
+ case VFY_OK:
+ if (!IE_ISGOOD(u->u.party_alerting.epref))
+ /* this happens when the EPREF has bad format.
+ * The rules require us the message to be ignored
+ * (9.5.3.2.2e) and to report status.
+ */
+ goto report;
+ break;
+ }
+ if (legal) {
+ /* p is != NULL here */
+ uni_enq_party(p, SIGP_ADD_PARTY_ACK, 0, m, u);
+ return;
+ }
+ if (p == NULL)
+ /* Q.2971 9.5.3.2.3a) */
+ respond_drop_party_ack(c, &u->u.add_party_ack.epref,
+ UNI_CAUSE_ENDP_INV);
+ else
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party_ack.epref, p->state);
+
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * Make the EPREF action default
+ */
+static void
+default_act_epref(struct uni *uni, struct uni_ie_epref *epref)
+{
+ struct uni_ierr *e;
+
+ FOREACH_ERR(e, uni)
+ if (e->ie == UNI_IE_EPREF) {
+ e->act = UNI_IEACT_DEFAULT;
+ break;
+ }
+ epref->h.act = UNI_IEACT_DEFAULT;
+}
+
+/*
+ * PARTY ALERTING message
+ *
+ * Q.2971:Call-Control-U 9/39 U4
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-N 12/39 N7
+ * Q.2971:Call-Control-N 15/39 N8
+ * Q.2971:Call-Control-N 22/39 N10
+ */
+static void
+unx_party_alerting(struct call *c, struct uni_msg *m, struct uni_all *u,
+ int legal)
+{
+ struct party *p = NULL;
+
+ if (IE_ISGOOD(u->u.party_alerting.epref)) {
+ if (u->u.party_alerting.epref.flag == 0) {
+ IE_SETERROR(u->u.party_alerting.epref);
+ (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF,
+ u->u.party_alerting.epref.h.act, UNI_IERR_BAD);
+ } else {
+ p = uni_find_partyx(c, u->u.party_alerting.epref.epref, 1);
+ if (p == NULL) {
+ respond_drop_party_ack(c,
+ &u->u.party_alerting.epref,
+ UNI_CAUSE_ENDP_INV);
+ goto ignore;
+ }
+ }
+ }
+ uni_mandate_epref(c->uni, &u->u.party_alerting.epref);
+
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ goto ignore;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ report:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), &u->u.party_alerting.epref,
+ p ? p->state : UNI_EPSTATE_NULL);
+ case VFY_I:
+ goto ignore;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate), &u->u.party_alerting.epref,
+ p ? UNI_EPSTATE_ALERT_RCVD : UNI_EPSTATE_NULL);
+ if (!IE_ISGOOD(u->u.party_alerting.epref))
+ /* See below */
+ goto ignore;
+ break;
+
+ case VFY_OK:
+ if (!IE_ISGOOD(u->u.party_alerting.epref))
+ /* The rules require us the message to be ignored
+ * (9.5.3.2.2e) and to report status.
+ */
+ goto report;
+ break;
+ }
+ if (legal) {
+ /* p is != NULL here */
+ uni_enq_party(p, SIGP_PARTY_ALERTING, 0, m, u);
+ return;
+ }
+ if (p == NULL)
+ /* Q.2971 9.5.3.2.3a) */
+ respond_drop_party_ack(c, &u->u.party_alerting.epref,
+ UNI_CAUSE_ENDP_INV);
+ else
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.party_alerting.epref, p->state);
+
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * Handle a bad/missing cause in a DROP_PARTY_ACK or ADD_PARTY_REJ
+ *
+ * If the IE is missing or bad and the action is defaulted handle as
+ * cause #1 according to 9.5.7.1/2.
+ * Otherwise keep the IE.
+ */
+static void
+handle_bad_drop_cause(struct call *c, struct uni_ie_cause *cause, int mkcause)
+{
+
+ if (IE_ISGOOD(*cause))
+ return;
+
+ if (!IE_ISPRESENT(*cause)) {
+ /* 9.5.7.1 */
+ /* cannot make cause here because we need the 96 error */
+ uni_vfy_remove_cause(c->uni);
+ return;
+ }
+ if (cause->h.act != UNI_IEACT_DEFAULT)
+ return;
+
+ /* 9.5.7.2 */
+ uni_vfy_remove_cause(c->uni);
+ if (mkcause)
+ MK_IE_CAUSE(*cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_UNSPEC);
+}
+
+/*
+ * ADD PARTY REJ from party control
+ * Q.2971:Call-Control-U 21/39
+ * Q.2971:Call-Control-U 24/39
+ */
+static void
+unx_send_add_party_rej(struct call *c, struct uni_all *u)
+{
+
+ if (uni_party_act_count(c, 2) == 0) {
+ if (c->cstate != CALLST_U11 && c->cstate != CALLST_N12) {
+ c->uni->cause = u->u.add_party_rej.cause;
+ clear_callD(c);
+ }
+ } else
+ (void)uni_send_output(u, c->uni);
+ UNI_FREE(u);
+}
+
+/*
+ * ADD_PARTY_REJECT in U4/U10
+ *
+ * Q.2971:Call-Control-U 9/39 U4
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-N 12/39 N7
+ * Q.2971:Call-Control-N 15/39 N8
+ * Q.2971:Call-Control-N 22/39 N10
+ */
+static void
+unx_add_party_rej(struct call *c, struct uni_msg *m, struct uni_all *u,
+ int legal)
+{
+ struct uni_add_party_rej *ar = &u->u.add_party_rej;
+ struct party *p;
+
+ if (IE_ISGOOD(ar->epref)) {
+ p = uni_find_partyx(c, ar->epref.epref, ar->epref.flag);
+ if (p == NULL)
+ goto ignore;
+
+ if (legal) {
+ handle_bad_drop_cause(c, &ar->cause, 0);
+ uni_vfy_remove_unknown(c->uni);
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ goto clear;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ uni_respond_status_verify(c->uni,
+ &u->u.hdr.cref, map_callstate(c->cstate),
+ &ar->epref, p->state);
+ case VFY_I:
+ goto ignore;
+
+ case VFY_RAPU:
+ uni_vfy_collect_ies(c->uni);
+ break;
+
+ case VFY_RAP:
+ uni_respond_status_verify(c->uni,
+ &u->u.hdr.cref, map_callstate(c->cstate),
+ &ar->epref, p->state);
+ case VFY_OK:
+ break;
+ }
+ uni_enq_party(p, SIGP_ADD_PARTY_REJ, 0, m, u);
+ return;
+ }
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &ar->epref, -1);
+ return;
+ }
+
+ /* Q.2971: 9.5.3.2.1 last paragraph
+ * 9.5.3.2.2 second to last paragraph
+ * Make the action indicator default.
+ */
+ default_act_epref(c->uni, &ar->epref);
+ if (!IE_ISPRESENT(ar->epref))
+ uni_mandate_ie(c->uni, UNI_IE_EPREF);
+ (void)uni_verify(c->uni, u->u.hdr.act);
+
+ clear:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * DROP_PARTY
+ *
+ * Q.2971:Call-Control-U 26/39 Ux
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-N 27/39 Nx
+ * Q.2971:Call-Control-N 22/39 N10
+ */
+static void
+unx_drop_party(struct call *c, struct uni_msg *m, struct uni_all *u, int legal)
+{
+ struct uni_drop_party *dp = &u->u.drop_party;
+ struct party *p;
+ struct uni_ierr *e;
+
+ if (IE_ISGOOD(dp->epref)) {
+ p = uni_find_partyx(c, dp->epref.epref, dp->epref.flag);
+ if (p == NULL) {
+ respond_drop_party_ack(c, &dp->epref,
+ UNI_CAUSE_ENDP_INV);
+ goto ignore;
+ }
+ handle_bad_drop_cause(c, &dp->cause, 0);
+ uni_vfy_remove_unknown(c->uni);
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ goto clear;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate),
+ &u->u.drop_party.epref, p->state);
+ case VFY_I:
+ goto ignore;
+
+ case VFY_RAPU:
+ uni_vfy_collect_ies(c->uni);
+ break;
+
+ case VFY_RAP:
+ uni_respond_status_verify(c->uni, &u->u.hdr.cref,
+ map_callstate(c->cstate),
+ &dp->epref, UNI_EPSTATE_DROP_RCVD);
+ case VFY_OK:
+ break;
+ }
+ if (legal) {
+ uni_enq_party(p, SIGP_DROP_PARTY, 0, m, u);
+ return;
+ }
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, &dp->epref, -1);
+ goto ignore;
+ }
+
+ /* Q.2971: 9.5.3.2.1 last paragraph
+ * 9.5.3.2.2 second to last paragraph
+ * Make the action indicator default.
+ */
+ FOREACH_ERR(e, c->uni)
+ if (e->ie == UNI_IE_EPREF) {
+ e->act = UNI_IEACT_DEFAULT;
+ break;
+ }
+ dp->epref.h.act = UNI_IEACT_DEFAULT;
+
+ if (!IE_ISPRESENT(dp->epref))
+ uni_mandate_ie(c->uni, UNI_IE_EPREF);
+ (void)uni_verify(c->uni, u->u.hdr.act);
+
+ clear:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * DROP_PARTY_ACK
+ *
+ * Q.2971:Call-Control-U 26/39 Ux
+ * Q.2971:Call-Control-U 21/39 U10
+ * Q.2971:Call-Control-N 27/39 Nx
+ * Q.2971:Call-Control-N 22/39 N10
+ */
+static void
+unx_drop_party_ack(struct call *c, struct uni_msg *m, struct uni_all *u,
+ int legal)
+{
+ struct party *p;
+ struct uni_drop_party_ack *ack = &u->u.drop_party_ack;
+
+ if (IE_ISGOOD(u->u.drop_party_ack.epref)) {
+ p = uni_find_partyx(c, ack->epref.epref, ack->epref.flag);
+ if (p != NULL) {
+ handle_bad_drop_cause(c, &ack->cause, 1);
+ uni_vfy_remove_unknown(c->uni);
+ switch (uni_verify(c->uni, u->u.hdr.act)) {
+
+ case VFY_CLR:
+ goto clear;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ uni_respond_status_verify(c->uni,
+ &u->u.hdr.cref, map_callstate(c->cstate),
+ &ack->epref, p->state);
+ case VFY_I:
+ goto ignore;
+
+ case VFY_RAP:
+ uni_respond_status_verify(c->uni,
+ &u->u.hdr.cref, map_callstate(c->cstate),
+ &ack->epref, UNI_EPSTATE_NULL);
+ case VFY_RAPU:
+ case VFY_OK:
+ break;
+ }
+ if (legal) {
+ uni_enq_party(p, SIGP_DROP_PARTY_ACK, 0, m, u);
+ return;
+ }
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &ack->epref, -1);
+ }
+ goto ignore;
+ }
+
+ /* Q.2971: 9.5.3.2.1 last paragraph
+ * 9.5.3.2.2 second to last paragraph
+ */
+ (void)uni_verify(c->uni, u->u.hdr.act);
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_IE_INV);
+
+ clear:
+ uni_vfy_collect_ies(c->uni);
+ clear_callD(c);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+
+ ignore:
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/**********************************************************************/
+
+/*
+ * Bad or unrecognized message.
+ *
+ * Q.2971:Call-Control-U 35/39
+ */
+void
+uni_bad_message(struct call *c, struct uni_all *u, u_int cause,
+ struct uni_ie_epref *epref, int ps)
+{
+ struct uni_all *resp;
+ struct party *p;
+
+ if ((u->u.hdr.act == UNI_MSGACT_CLEAR &&
+ (c->cstate == CALLST_U11 ||
+ c->cstate == CALLST_U12 ||
+ c->cstate == CALLST_N11 ||
+ c->cstate == CALLST_N12)) ||
+ u->u.hdr.act == UNI_MSGACT_IGNORE)
+ return;
+
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, cause);
+ ADD_CAUSE_MTYPE(c->uni->cause, u->mtype);
+
+ if (u->u.hdr.act == UNI_MSGACT_CLEAR) {
+ clear_callD(c);
+ return;
+ }
+
+ /*
+ * Send STATUS
+ */
+ if ((resp = UNI_ALLOC()) != NULL) {
+ MK_MSG_RESP(resp, UNI_STATUS, &u->u.hdr.cref);
+ MK_IE_CALLSTATE(resp->u.status.callstate,
+ map_callstate(c->cstate));
+ resp->u.status.cause = c->uni->cause;
+
+ if (epref != NULL && IE_ISGOOD(*epref)) {
+ MK_IE_EPREF(resp->u.status.epref, epref->epref, !epref->flag);
+ if (ps == -1) {
+ p = uni_find_party(c, epref);
+ if (p == NULL)
+ ps = UNI_EPSTATE_NULL;
+ else
+ ps = p->state;
+ }
+ MK_IE_EPSTATE(resp->u.status.epstate, ps);
+ }
+ (void)uni_send_output(resp, c->uni);
+
+ UNI_FREE(resp);
+ }
+}
+
+/**********************************************************************/
+
+/*
+ * Unknown message in any state.
+ *
+ * Q.2971:Call-Control 35/39
+ * Q.2971:Call-Control 36/39
+ */
+static void
+unx_unknown(struct call *c, struct uni_msg *m, struct uni_all *u)
+{
+ /*
+ * Unrecognized message. Cannot call verify here, because
+ * it doesn't know about unrecognized messages.
+ */
+ if (u->u.hdr.act == UNI_MSGACT_CLEAR) {
+ MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MTYPE_NIMPL);
+ ADD_CAUSE_MTYPE(c->uni->cause, u->mtype);
+ clear_callD(c);
+ } else if(u->u.hdr.act == UNI_MSGACT_IGNORE) {
+ ;
+ } else {
+ (void)uni_decode_body(m, u, &c->uni->cx);
+ uni_bad_message(c, u, UNI_CAUSE_MTYPE_NIMPL,
+ &u->u.unknown.epref, -1);
+ }
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+/**********************************************************************/
+
+void
+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) {
+ VERBOSE(c->uni, UNI_FAC_ERR, 1,
+ "Signal %d outside of range to Call-Control", sig);
+ if (msg)
+ uni_msg_destroy(msg);
+ if (u)
+ UNI_FREE(u);
+ return;
+ }
+
+ VERBOSE(c->uni, UNI_FAC_CALL, 1, "Signal %s in state %s of call %u/%s"
+ "; cookie %u", call_sigs[sig], callstates[c->cstate].name, c->cref,
+ c->mine ? "mine" : "his", cookie);
+
+ switch (sig) {
+
+ case SIGC_LINK_RELEASE_indication:
+ if (c->cstate == CALLST_U10 || c->cstate == CALLST_N10)
+ /* Q.2971:Call-Control-U 36/39 */
+ /* Q.2971:Call-Control-N 20/39 */
+ un10_link_release_indication(c);
+ else
+ /* Q.2971:Call-Control-U 36/39 */
+ /* Q.2971:Call-Control-N 37/39 */
+ unx_link_release_indication(c);
+ break;
+
+ case SIGC_LINK_ESTABLISH_ERROR_indication:
+ if (c->cstate != CALLST_U10 && c->cstate != CALLST_N10) {
+ VERBOSE(c->uni, UNI_FAC_ERR, 1,
+ "link-establish-error.indication in cs=%s",
+ callstates[c->cstate].name);
+ break;
+ }
+ /* Q.2971:Call-Control-U 19/39 */
+ /* Q.2971:Call-Control-N 20/39 */
+ un10_link_establish_error_indication(c);
+ break;
+
+ case SIGC_LINK_ESTABLISH_indication:
+ switch (c->cstate) {
+
+ case CALLST_U1: case CALLST_N1:
+ case CALLST_U3: case CALLST_N3:
+ case CALLST_U4: case CALLST_N4:
+ case CALLST_U6: case CALLST_N6:
+ case CALLST_U7: case CALLST_N7:
+ case CALLST_U8: case CALLST_N8:
+ case CALLST_U9: case CALLST_N9:
+ /* Q.2971:Call-Control-U 36/39 */
+ /* Q.2971:Call-Control-N 37/39 */
+ unx_link_establish_indication(c);
+ break;
+
+ case CALLST_U10: case CALLST_N10:
+ /* Q.2971:Call-Control-U 19/39 */
+ /* Q.2971:Call-Control-N 20/39 */
+ un10_link_establish_indication(c);
+ break;
+
+ case CALLST_U11: case CALLST_N11:
+ case CALLST_U12: case CALLST_N12:
+ /* Q.2971:Call-Control-U 36/39 */
+ /* Q.2971:Call-Control-N 37/39 */
+ break;
+
+ default:
+ VERBOSE(c->uni, UNI_FAC_ERR, 1,
+ "link-establish.indication in cs=%s",
+ callstates[c->cstate].name);
+ }
+ break;
+
+ case SIGC_LINK_ESTABLISH_confirm:
+ if (c->cstate != CALLST_U10 && c->cstate != CALLST_N10) {
+ VERBOSE(c->uni, UNI_FAC_ERR, 1,
+ "link-establish.confirm in cs=%s",
+ callstates[c->cstate].name);
+ break;
+ }
+ /* Q.2971:Call-Control-U 19/39 */
+ /* Q.2971:Call-Control-N 20/39 */
+ un10_link_establish_confirm(c);
+ break;
+
+ case SIGC_UNKNOWN:
+ /* Q.2971:Call-Control 35/39 */
+ /* Q.2971:Call-Control 36/39 */
+ unx_unknown(c, msg, u);
+ break;
+
+ case SIGC_SETUP:
+ if (c->cstate != CALLST_NULL) {
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.setup.epref, -1);
+ goto drop;
+ }
+ if (c->uni->proto == UNIPROTO_UNI40N)
+ /* Q.2971:Call-Control-N 4/39 */
+ un0_setup(c, msg, u, CALLST_N1);
+ else
+ /* Q.2971:Call-Control-U 4/39 */
+ un0_setup(c, msg, u, CALLST_U6);
+ break;
+
+ case SIGC_CALL_PROC:
+ if (c->cstate == CALLST_U1) {
+ /* Q.2971:Call-Control-U 6/39 */
+ u1n6_call_proc(c, msg, u, CALLST_U3);
+ break;
+ }
+ if (c->cstate == CALLST_N6) {
+ /* Q.2971:Call-Control-N 11/39 */
+ u1n6_call_proc(c, msg, u, CALLST_N9);
+ break;
+ }
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.call_proc.epref, -1);
+ goto drop;
+
+ case SIGC_ALERTING:
+ if (c->cstate == CALLST_U1 || c->cstate == CALLST_U3) {
+ /* Q.2971:Call-Control-U 37/39 (U1) */
+ /* Q.2971:Call-Control-U 7/39 (U3) */
+ unx_alerting(c, msg, u, CALLST_U4);
+ break;
+ }
+ if (c->cstate == CALLST_N6) {
+ /* Q.2971:Call-Control-N 9/39 (N6) */
+ /* Q.2971:Call-Control-N 17/39 (N9) */
+ unx_alerting(c, msg, u, CALLST_N7);
+ break;
+ }
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.alerting.epref, -1);
+ goto drop;
+
+ case SIGC_CONNECT:
+ if (c->cstate == CALLST_U1 || c->cstate == CALLST_U3 ||
+ c->cstate == CALLST_U4) {
+ /* Q.2971:Call-Control-U 7-8/39 (U3) */
+ /* Q.2971:Call-Control-U 11/39 (U4) */
+ /* Q.2971:Call-Control-U 37/39 (U1) */
+ unx_connect(c, msg, u, CALLST_U10);
+ break;
+ }
+ if (c->cstate == CALLST_N6 || c->cstate == CALLST_N7 ||
+ c->cstate == CALLST_N9) {
+ /* Q.2971:Call-Control-N 9-10/39 (N6) */
+ /* Q.2971:Call-Control-N 14/39 (N7) */
+ /* Q.2971:Call-Control-N 17/39 (N9) */
+ unx_connect(c, msg, u, CALLST_N8);
+ break;
+ }
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.connect.epref, -1);
+ goto drop;
+
+ case SIGC_CONNECT_ACK:
+ if (c->cstate == CALLST_U8) {
+ /* Q.2971:Call-Control-U 15-16/39 */
+ u8_connect_ack(c, msg, u, CALLST_U10);
+ break;
+ }
+ if (c->cstate == CALLST_N10) {
+ /* Q.2971:Call-Control-N 18/39 */
+ n10_connect_ack(c, msg, u);
+ break;
+ }
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, NULL, 0);
+ goto drop;
+
+ case SIGC_RELEASE:
+ switch (c->cstate) {
+
+ default:
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, NULL, 0);
+ goto drop;
+
+ case CALLST_U11:
+ case CALLST_N12:
+ /* Q.2971:Call-Control-U 28/39 */
+ /* Q.2971:Call-Control-N 30/39 */
+ u11n12_release(c, msg, u);
+ break;
+
+ case CALLST_U1:
+ case CALLST_U3:
+ case CALLST_U4:
+ case CALLST_U6:
+ case CALLST_U7:
+ case CALLST_U8:
+ case CALLST_U9:
+ case CALLST_U10:
+ case CALLST_U12:
+ /* Q.2971:Call-Control-U 25/39 */
+ unx_release(c, msg, u, CALLST_U12);
+ break;
+
+ case CALLST_N1:
+ case CALLST_N3:
+ case CALLST_N4:
+ case CALLST_N6:
+ case CALLST_N7:
+ case CALLST_N8:
+ case CALLST_N9:
+ case CALLST_N10:
+ case CALLST_N11:
+ /* Q.2971:Call-Control-N 26/39 */
+ unx_release(c, msg, u, CALLST_N11);
+ break;
+ }
+ break;
+
+ case SIGC_RELEASE_COMPL:
+ /* Q.2971:Call-Control-U 25/39 */
+ /* Q.2971:Call-Control-N 26/39 */
+ unx_release_compl(c, msg, u);
+ break;
+
+ case SIGC_NOTIFY:
+ /* Q.2971:Call-Control-U 18/39 */
+ /* Q.2971:Call-Control-N 19/39 */
+ unx_notify(c, msg, u);
+ break;
+
+ case SIGC_STATUS:
+ if (c->cstate == CALLST_U11 || c->cstate == CALLST_U12 ||
+ c->cstate == CALLST_N11 || c->cstate == CALLST_N12) {
+ /* Q.2971:Call-Control-U 29/39 (U11) */
+ /* Q.2971:Call-Control-U 30/39 (U12) */
+ /* Q.2971:Call-Control-N 29/39 (N11) */
+ /* Q.2971:Call-Control-N 31/39 (N12) */
+ un11un12_status(c, msg, u);
+ break;
+ }
+ /* Q.2971:Call-Control-U 32/39 */
+ /* Q.2971:Call-Control-N 33/39 */
+ unx_status(c, msg, u);
+ break;
+
+ case SIGC_STATUS_ENQ:
+ /* Q.2971:Call-Control-U 31/39 */
+ /* Q.2971:Call-Control-N 32/39 */
+ unx_status_enq(c, msg, u);
+ break;
+
+ case SIGC_ADD_PARTY:
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+
+ if (c->type != CALL_LEAF && c->type != CALL_ROOT) {
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party.epref, UNI_EPSTATE_NULL);
+ goto drop;
+ }
+ switch (c->cstate) {
+ case CALLST_U7:
+ case CALLST_U8:
+ case CALLST_U10:
+ case CALLST_N4:
+ case CALLST_N10:
+ /* Q.2971:Call-Control-U 14/39 U7 */
+ /* Q.2971:Call-Control-U 15/39 U8 */
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-N 8/39 N4 */
+ /* Q.2971:Call-Control-N 21/39 N10 */
+ unx_add_party(c, msg, u, 1);
+ break;
+
+ default:
+ unx_add_party(c, msg, u, 0);
+ goto drop;
+ }
+ break;
+
+ case SIGC_PARTY_ALERTING:
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+
+ if (c->type != CALL_ROOT) {
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.party_alerting.epref, -1);
+ goto drop;
+ }
+ switch (c->cstate) {
+
+ default:
+ /* Q.2971 9.5.3.2.3a) */
+ unx_party_alerting(c, msg, u, 0);
+ break;
+
+ case CALLST_U4:
+ case CALLST_U10:
+ /* Q.2971:Call-Control-U 9/39 U4 */
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-N 12/39 N7 */
+ /* Q.2971:Call-Control-N 15/39 N8 */
+ /* Q.2971:Call-Control-N 22/39 N10 */
+ unx_party_alerting(c, msg, u, 1);
+ break;
+ }
+ break;
+
+ case SIGC_ADD_PARTY_ACK:
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+
+ if (c->type != CALL_ROOT) {
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party_rej.epref, -1);
+ goto drop;
+ }
+ switch (c->cstate) {
+
+ case CALLST_U10:
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-N 15/39 N8 */
+ /* Q.2971:Call-Control-N 22/39 N10 */
+ un10n8_add_party_ack(c, msg, u, 1);
+ break;
+
+ default:
+ /* Q.2971 9.5.3.2.3a) */
+ un10n8_add_party_ack(c, msg, u, 0);
+ break;
+ }
+ break;
+
+ case SIGC_ADD_PARTY_REJ:
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+
+ if (c->type != CALL_ROOT) {
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party_rej.epref, -1);
+ goto drop;
+ }
+ switch (c->cstate) {
+
+ case CALLST_U4:
+ case CALLST_U10:
+ case CALLST_N7:
+ case CALLST_N8:
+ case CALLST_N10:
+ /* Q.2971:Call-Control-U 9/39 U4 */
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-N 12/39 N7 */
+ /* Q.2971:Call-Control-N 15/39 N8 */
+ /* Q.2971:Call-Control-N 22/39 N10 */
+ unx_add_party_rej(c, msg, u, 1);
+ break;
+
+ default:
+ /* Q.2971: 9.5.3.2.3b */
+ unx_add_party_rej(c, msg, u, 0);
+ break;
+ }
+ break;
+
+ case SIGC_DROP_PARTY:
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+
+ if (c->type != CALL_ROOT && c->type != CALL_LEAF) {
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.drop_party.epref, -1);
+ goto drop;
+ }
+ switch (c->cstate) {
+ case CALLST_U11:
+ case CALLST_U12:
+ case CALLST_N11:
+ case CALLST_N12:
+ /* Q.2971:Call-Control-U 28/39 U11 */
+ /* Q.2971:Call-Control-U 30/39 U12 */
+ /* Q.2971:Call-Control-N 29/39 N11 */
+ /* Q.2971:Call-Control-N 30/39 N12 */
+ goto drop;
+
+ case CALLST_NULL:
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.drop_party.epref, UNI_EPSTATE_NULL);
+ goto drop;
+
+ case CALLST_U3:
+ case CALLST_N3:
+ /* L3MU_17_38 */
+ unx_drop_party(c, msg, u, 0);
+ break;
+
+ case CALLST_U8:
+ if (c->uni->sb_tb) {
+ /* L3MU_06_0[3-6] */
+ unx_drop_party(c, msg, u, 0);
+ break;
+ }
+ /* FALLTHRU */
+
+ default:
+ /* Q.2971:Call-Control-U 26/39 Ux */
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-N 27/39 Nx */
+ /* Q.2971:Call-Control-N 21/39 N10 */
+ unx_drop_party(c, msg, u, 1);
+ break;
+ }
+ break;
+
+ case SIGC_DROP_PARTY_ACK:
+ (void)uni_decode_body(msg, u, &c->uni->cx);
+
+ if (c->type != CALL_ROOT && c->type != CALL_LEAF) {
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.drop_party_ack.epref, -1);
+ goto drop;
+ }
+ switch (c->cstate) {
+
+ case CALLST_U11:
+ case CALLST_U12:
+ /* Q.2971:Call-Control-U 28/39 U11 */
+ /* Q.2971:Call-Control-U 30/39 U12 */
+ /* Q.2971:Call-Control-N 29/39 N11 */
+ /* Q.2971:Call-Control-N 30/39 N12 */
+ goto drop;
+
+ case CALLST_NULL:
+ uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.drop_party.epref, UNI_EPSTATE_NULL);
+ goto drop;
+
+ case CALLST_U4:
+ case CALLST_N4:
+ case CALLST_U7:
+ case CALLST_N7:
+ case CALLST_U8:
+ case CALLST_N8:
+ case CALLST_U10:
+ case CALLST_N10:
+ /* Q.2971:Call-Control-U 26/39 Ux */
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-N 27/39 Nx */
+ /* Q.2971:Call-Control-N 22/39 N10 */
+ unx_drop_party_ack(c, msg, u, 1);
+ break;
+
+ default:
+ /* Q.2971 10.5 4th paragraph */
+ unx_drop_party_ack(c, msg, u, 0);
+ break;
+ }
+ break;
+
+ case SIGC_COBISETUP: /* XXX */
+ unx_unknown(c, msg, u);
+ break;
+
+ /*
+ * User signals
+ */
+ case SIGC_SETUP_request:
+ if (c->cstate == CALLST_NULL) {
+ /* Q.2971:Call-Control-U 4/39 (U0) */
+ /* Q.2971:Call-Control-N 4/39 (N0) */
+ if (c->uni->proto == UNIPROTO_UNI40N)
+ un0_setup_request(c, msg, cookie, CALLST_N6);
+ else
+ un0_setup_request(c, msg, cookie, CALLST_U1);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "setup.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_SETUP_response:
+ if (c->cstate == CALLST_U6 || c->cstate == CALLST_U9 ||
+ c->cstate == CALLST_U7) {
+ /* Q.2971:Call-Control-U 13/39 (U6) */
+ /* Q.2971:Call-Control-U 14/39 (U7) */
+ /* Q.2971:Call-Control-U 17/39 (U9) */
+ unx_setup_response(c, msg, cookie, CALLST_U8);
+ break;
+ }
+ if (c->cstate == CALLST_N1 || c->cstate == CALLST_N3 ||
+ c->cstate == CALLST_N4) {
+ /* Q.2971:Call-Control-N 39/39 (N1) */
+ /* Q.2971:Call-Control-N 7/39 (N3) */
+ /* Q.2971:Call-Control-N 8/39 (N4) */
+ unx_setup_response(c, msg, cookie, CALLST_N10);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "setup.response in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_SETUP_COMPLETE_request:
+ if (c->cstate == CALLST_N8) {
+ /* Q.2971:Call-Control-N 15/39 (N8) */
+ n8_setup_compl_request(c, msg, cookie, CALLST_N10);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "setup_compl.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_PROCEEDING_request:
+ if (c->cstate == CALLST_U6) {
+ /* Q.2971:Call-Control-U 12/39 (U6) */
+ u6n1_proceeding_request(c, msg, cookie, CALLST_U9);
+ break;
+ }
+ if (c->cstate == CALLST_N1) {
+ /* Q.2971:Call-Control-N 6/39 (N1) */
+ u6n1_proceeding_request(c, msg, cookie, CALLST_N3);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "proceeding.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_ALERTING_request:
+ if (c->cstate == CALLST_U6 || c->cstate == CALLST_U9) {
+ /* Q.2971:Call-Control-U 13/39 (U6) */
+ /* Q.2971:Call-Control-U 17/39 (U9) */
+ unx_alerting_request(c, msg, cookie, CALLST_U7);
+ break;
+ }
+ 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);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "alerting.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_RELEASE_request:
+ switch (c->cstate) {
+
+ case CALLST_U1:
+ case CALLST_U3:
+ case CALLST_U4:
+ case CALLST_U6:
+ case CALLST_U7:
+ case CALLST_U8:
+ case CALLST_U9:
+ case CALLST_U10:
+ /* Q.2971:Call-Control-U 27/39 */
+ unx_release_request(c, msg, cookie, CALLST_U11);
+ break;
+
+ case CALLST_N1:
+ case CALLST_N3:
+ case CALLST_N4:
+ case CALLST_N6:
+ case CALLST_N7:
+ case CALLST_N8:
+ case CALLST_N9:
+ case CALLST_N10:
+ /* Q.2971:Call-Control-N 28/39 */
+ unx_release_request(c, msg, cookie, CALLST_N12);
+ break;
+
+ case CALLST_U11:
+ case CALLST_U12:
+ case CALLST_N11:
+ case CALLST_N12:
+ case CALLST_NULL:
+ VERBOSE(c->uni, UNI_FAC_ERR, 1,
+ "release.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE,
+ cookie);
+ uni_msg_destroy(msg);
+ break;
+ }
+ break;
+
+ case SIGC_RELEASE_response:
+ if (c->cstate == CALLST_U6 || c->cstate == CALLST_U12 ||
+ c->cstate == CALLST_N1 || c->cstate == CALLST_N11) {
+ /* Q.2971:Call-Control-U 12/39 (U6) */
+ /* Q.2971:Call-Control-U 30/39 (U12) */
+ /* Q.2971:Call-Control-N 6/39 (N1) */
+ /* Q.2971:Call-Control-N 29/39 (N11) */
+ unx_release_response(c, msg, cookie);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "release.response in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_NOTIFY_request:
+ /* Q.2971:Call-Control-U 18/39 */
+ /* Q.2971:Call-Control-N 19/39 */
+ unx_notify_request(c, msg, cookie);
+ break;
+
+ case SIGC_STATUS_ENQUIRY_request:
+ /* Q.2971:Call-Control-U 31/39 */
+ /* Q.2971:Call-Control-N 32/39 */
+ unx_status_enquiry_request(c, msg, cookie);
+ break;
+
+ case SIGC_ADD_PARTY_request:
+ if (c->cstate == CALLST_U4 || c->cstate == CALLST_U10 ||
+ c->cstate == CALLST_N7 || c->cstate == CALLST_N10) {
+ /* Q.2971:Call-Control-U 9-10/39 (U4) */
+ /* Q.2971:Call-Control-U 21/39 (U10) */
+ /* Q.2971:Call-Control-N 12/39 (N7) */
+ /* Q.2971:Call-Control-N 22/39 (N10) */
+ unx_add_party_request(c, msg, cookie);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "add-party.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_PARTY_ALERTING_request:
+ if (c->cstate == CALLST_U7 || c->cstate == CALLST_U8 ||
+ c->cstate == CALLST_U10 ||
+ c->cstate == CALLST_N4 || c->cstate == CALLST_N10) {
+ /* Q.2971:Call-Control-U 14/39 U7 */
+ /* Q.2971:Call-Control-U 15/39 U8 */
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-N 8/39 N4 */
+ /* Q.2971:Call-Control-N 22/39 N10 */
+ unx_party_alerting_request(c, msg, cookie);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1,
+ "party-alerting.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_ADD_PARTY_ACK_request:
+ if (c->cstate == CALLST_U10 || c->cstate == CALLST_N10) {
+ /* Q.2971:Call-Control-U 21/39 (U10) */
+ /* Q.2971:Call-Control-N 22/39 (N10)*/
+ un10_add_party_ack_request(c, msg, cookie);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1,
+ "add-party-ack.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_ADD_PARTY_REJ_request:
+ if (c->cstate == CALLST_U7 || c->cstate == CALLST_U8 ||
+ c->cstate == CALLST_U10 ||
+ c->cstate == CALLST_N4 || c->cstate == CALLST_N10) {
+ /* Q.2971:Call-Control-U 14/39 U7 */
+ /* Q.2971:Call-Control-U 15/39 U8 */
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-N 8/39 N4 */
+ /* Q.2971:Call-Control-N 22/39 N10 */
+ unx_add_party_rej_request(c, msg, cookie);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1,
+ "add-party-rej.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_DROP_PARTY_request:
+ if (c->cstate != CALLST_U11 && c->cstate != CALLST_U12 &&
+ c->cstate != CALLST_N11 && c->cstate != CALLST_N12 &&
+ c->cstate != CALLST_NULL) {
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-U 26/39 U1-U9 */
+ /* Q.2971:Call-Control-N 22/39 N10 */
+ /* Q.2971:Call-Control-N 27/39 N1-N9 */
+ unx_drop_party_request(c, msg, cookie);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "drop-party.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_DROP_PARTY_ACK_request:
+ if (c->cstate != CALLST_U11 && c->cstate != CALLST_U12 &&
+ c->cstate != CALLST_N11 && c->cstate != CALLST_N12 &&
+ c->cstate != CALLST_NULL) {
+ /* Q.2971:Call-Control-U 21/39 U10 */
+ /* Q.2971:Call-Control-U 26/39 U1-U9 */
+ /* Q.2971:Call-Control-N 22/39 N10 */
+ /* Q.2971:Call-Control-N 27/39 N1-N9 */
+ unx_drop_party_ack_request(c, msg, cookie);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1,
+ "drop-party-ack.request in cs=%s",
+ callstates[c->cstate].name);
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGC_ABORT_CALL_request:
+ {
+ struct uni *uni = c->uni;
+
+ uni_destroy_call(c, 0);
+ uniapi_uni_error(uni, UNIAPI_OK, cookie, UNI_CALLSTATE_U0);
+ break;
+ }
+
+ /*
+ * Timers
+ */
+ case SIGC_T301:
+ if (c->cstate == CALLST_U4 || c->cstate == CALLST_N7) {
+ /* Q.2971:Call-Control-U Missing */
+ /* Q.2971:Call-Control-N 14/39 */
+ u4n7_t301(c);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "T301 in cs=%s",
+ callstates[c->cstate].name);
+ break;
+
+ case SIGC_T303:
+ if (c->cstate == CALLST_U1 || c->cstate == CALLST_N6) {
+ /* Q.2971:Call-Control-U 6/39 */
+ /* Q.2971:Call-Control-N 11/39 */
+ u1n6_t303(c);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "T303 in cs=%s",
+ callstates[c->cstate].name);
+ break;
+
+ case SIGC_T308:
+ if (c->cstate == CALLST_U11 || c->cstate == CALLST_N12) {
+ /* Q.2971:Call-Control-U 28/39 */
+ /* Q.2971:Call-Control-N 30/39 */
+ u11n12_t308(c);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "T308 in cs=%s",
+ callstates[c->cstate].name);
+ break;
+
+ case SIGC_T310:
+ if (c->cstate == CALLST_U3 || c->cstate == CALLST_N9) {
+ /* Q.2971:Call-Control-U 7/39 */
+ /* Q.2971:Call-Control-N 17/39 */
+ u3n9_t310(c);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "T310 in cs=%s",
+ callstates[c->cstate].name);
+ break;
+
+ case SIGC_T313:
+ if (c->cstate == CALLST_U8) {
+ /* Q.2971:Call-Control-U 15/39 */
+ u8_t313(c);
+ break;
+ }
+ VERBOSE(c->uni, UNI_FAC_ERR, 1, "T313 in cs=%s",
+ callstates[c->cstate].name);
+ break;
+
+ case SIGC_T322:
+ /* Q.2971:Call-Control-U 34/39 */
+ /* Q.2971:Call-Control-N 35/39 */
+ unx_t322(c);
+ break;
+
+ case SIGC_CALL_DELETE:
+ CALL_FREE(c);
+ break;
+
+ /*
+ * Party-Control
+ */
+ case SIGC_DROP_PARTY_indication:
+ if (c->uni->proto == UNIPROTO_UNI40U)
+ /* Q.2971:Call-Control-U 23/39 */
+ ux_drop_party_indication(c, msg);
+ else
+ /* Q.2971:Call-Control-N 23/39 */
+ nx_drop_party_indication(c, msg);
+ break;
+
+ case SIGC_DROP_PARTY_ACK_indication:
+ if (c->uni->proto == UNIPROTO_UNI40U)
+ /* Q.2971:Call-Control-U 23/39 */
+ ux_drop_party_ack_indication(c, msg);
+ else
+ /* Q.2971:Call-Control-N 23/39 */
+ nx_drop_party_ack_indication(c, msg);
+ break;
+
+ case SIGC_ADD_PARTY_REJ_indication:
+ if (c->uni->proto == UNIPROTO_UNI40U)
+ /* Q.2971:Call-Control-U 23/39 */
+ ux_add_party_rej_indication(c, msg);
+ else
+ /* Q.2971:Call-Control-N 23/39 */
+ nx_add_party_rej_indication(c, msg);
+ break;
+
+
+ case SIGC_SEND_DROP_PARTY:
+ /* Q.2971:Call-Control-U 21/39 */
+ /* Q.2971:Call-Control-U 25/39 */
+ if (uni_party_act_count(c, 2) != 0)
+ (void)uni_send_output(u, c->uni);
+ else if(c->cstate != CALLST_U11) {
+ c->uni->cause = u->u.drop_party.cause;
+ clear_callD(c);
+ }
+ UNI_FREE(u);
+ break;
+
+ case SIGC_SEND_DROP_PARTY_ACK:
+ /* Q.2971:Call-Control-U 21/39 */
+ /* Q.2971:Call-Control-U 25/39 */
+ if (uni_party_act_count(c, 2) != 0)
+ (void)uni_send_output(u, c->uni);
+ else if (c->cstate != CALLST_U11) {
+ c->uni->cause = u->u.drop_party_ack.cause;
+ clear_callD(c);
+ }
+ UNI_FREE(u);
+ break;
+
+ case SIGC_SEND_ADD_PARTY_REJ:
+ /* Q.2971:Call-Control-U 21/39 */
+ /* Q.2971:Call-Control-U 24/39 */
+ unx_send_add_party_rej(c, u);
+ break;
+
+ case SIGC_SEND_STATUS_ENQ:
+ /* Q.2971:Call-Control-U 21/39 */
+ /* Q.2971:Call-Control-U 25/39 */
+ unx_send_party_status_enq(c, u);
+ break;
+
+ case SIGC_PARTY_DESTROYED:
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_PARTY_DESTROYED, cookie, msg);
+ break;
+
+ case SIGC_END:
+ break;
+ }
+
+ return;
+
+ drop:
+ /*
+ * This is for SAAL message signals that should be dropped.
+ */
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+}
+
+/**********************************************************************/
+
+/*
+ * Timeout functions
+ */
+static void
+t308_func(struct call *c)
+{
+ uni_enq_call(c, SIGC_T308, 0, NULL, NULL);
+}
+static void
+t303_func(struct call *c)
+{
+ uni_enq_call(c, SIGC_T303, 0, NULL, NULL);
+}
+static void
+t301_func(struct call *c)
+{
+ uni_enq_call(c, SIGC_T301, 0, NULL, NULL);
+}
+static void
+t310_func(struct call *c)
+{
+ uni_enq_call(c, SIGC_T310, 0, NULL, NULL);
+}
+static void
+t313_func(struct call *c)
+{
+ uni_enq_call(c, SIGC_T313, 0, NULL, NULL);
+}
+
+static void
+t322_func(struct call *c)
+{
+ uni_enq_call(c, SIGC_T322, 0, NULL, NULL);
+}
+
+/**********************************************************************/
+
+/*
+ * Check whether the peer state is compatible with our state.
+ * Return the new callstate we should go to (either U0 or the current
+ * state).
+ * None of the state is U0 here. My state is not U11 or U12.
+ *
+ * Well, this turns out to be not so easy: the status enquiry could have
+ * been sent before we changed into the current state - the status will
+ * report a previous state without anything been lost.
+ *
+ * Incoming states are incompatible with outgoing states. Everything is ok.
+ */
+static enum call_state
+state_compat(struct call *c, enum uni_callstate peer)
+{
+ if ((c->cstate == CALLST_U1 ||
+ c->cstate == CALLST_U3 ||
+ c->cstate == CALLST_U4) &&
+ (peer == UNI_CALLSTATE_N6 ||
+ peer == UNI_CALLSTATE_N7 ||
+ peer == UNI_CALLSTATE_N8 ||
+ peer == UNI_CALLSTATE_N9))
+ return (CALLST_NULL);
+
+ if ((c->cstate == CALLST_N6 ||
+ c->cstate == CALLST_N7 ||
+ c->cstate == CALLST_N8 ||
+ c->cstate == CALLST_N9) &&
+ (peer == UNI_CALLSTATE_U1 ||
+ peer == UNI_CALLSTATE_U3 ||
+ peer == UNI_CALLSTATE_U4))
+ return (CALLST_NULL);
+
+ if ((peer == UNI_CALLSTATE_N1 ||
+ peer == UNI_CALLSTATE_N3 ||
+ peer == UNI_CALLSTATE_N4) &&
+ (c->cstate == CALLST_U6 ||
+ c->cstate == CALLST_U7 ||
+ c->cstate == CALLST_U8 ||
+ c->cstate == CALLST_N9))
+ return (CALLST_NULL);
+
+ if ((peer == UNI_CALLSTATE_U6 ||
+ peer == UNI_CALLSTATE_U7 ||
+ peer == UNI_CALLSTATE_U8 ||
+ peer == UNI_CALLSTATE_U9) &&
+ (c->cstate == CALLST_N1 ||
+ c->cstate == CALLST_N3 ||
+ c->cstate == CALLST_N4))
+ return (CALLST_NULL);
+
+ return (c->cstate);
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_coord.c b/sys/contrib/ngatm/netnatm/sig/sig_coord.c
new file mode 100644
index 000000000000..6a688302f053
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/sig_coord.c
@@ -0,0 +1,1171 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/sig_coord.c,v 1.12 2004/08/05 07:11:01 brandt Exp $
+ *
+ * Coordinator
+ */
+
+#include <netnatm/unimsg.h>
+#include <netnatm/saal/sscfudef.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/sig/uni.h>
+
+#include <netnatm/sig/unipriv.h>
+#include <netnatm/sig/unimkmsg.h>
+
+#define STR(S) [S] = #S
+static const char *const cunames[] = {
+ STR(CU_STAT0),
+ STR(CU_STAT1),
+ STR(CU_STAT2),
+ STR(CU_STAT3),
+};
+
+#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME,
+static const char *const coord_sigs[] = {
+ DEF_COORD_SIGS
+};
+#undef DEF_PRIV_SIG
+
+static void sig_all_calls(struct uni *, u_int sig);
+static void set_custat(struct uni *, enum cu_stat);
+
+static void input_dummy(struct uni *uni, struct uni_msg *m, struct uni_all *u);
+static void input_global(struct uni *uni, struct uni_msg *m, struct uni_all *u);
+static void input_unknown(struct uni *uni, struct uni_msg *m, struct uni_all *u);
+static void input_cobi(struct call *c, struct uni_msg *m, struct uni_all *u);
+static void input_call(struct call *c, struct uni_msg *m, struct uni_all *u);
+
+TIMER_FUNC_UNI(t309, t309_func)
+
+/*
+ * All those 'bogus signal' printouts are not specified in the SDLs.
+ */
+
+
+/*
+ * SAAL-ESTABLISH.indication
+ *
+ * This means either a resynchronisation or error-recovery or
+ * an incoming SSCOP connection.
+ */
+static void
+coord_saal_establish_indication(struct uni *uni)
+{
+ switch (uni->custat) {
+
+ case CU_STAT0: /* Q.2931:Coord-U 4/10 */
+ case CU_STAT3: /* Q.2931:Coord-U 5/10 */
+ sig_all_calls(uni, SIGC_LINK_ESTABLISH_indication);
+ set_custat(uni, CU_STAT3);
+ break;
+
+ case CU_STAT1:
+ case CU_STAT2:
+ VERBOSE0(uni, UNI_FAC_COORD,
+ "signal saal_establish.indication in CU%u", uni->custat);
+ break;
+
+ default:
+ ASSERT(0, ("CU_STAT*"));
+ }
+}
+
+/*
+ * SAAL-ESTABLISH.confirm
+ */
+static void
+coord_saal_establish_confirm(struct uni *uni)
+{
+ switch (uni->custat) {
+
+ case CU_STAT0:
+ case CU_STAT2:
+ VERBOSE0(uni, UNI_FAC_COORD,
+ "signal saal_establish.confirm in CU%u", uni->custat);
+ break;
+
+ case CU_STAT1:
+ /*
+ * Q.2931:Co-ord-U 4/10
+ */
+ TIMER_STOP_UNI(uni, t309);
+ sig_all_calls(uni, SIGC_LINK_ESTABLISH_confirm);
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_LINK_ESTABLISH_confirm, 0, NULL);
+ set_custat(uni, CU_STAT3);
+ break;
+
+ case CU_STAT3:
+ /*
+ * Q.2931:Coord-U 5/10
+ */
+ sig_all_calls(uni, SIGC_LINK_ESTABLISH_confirm);
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_LINK_ESTABLISH_confirm, 0, NULL);
+ break;
+
+ default:
+ ASSERT(0, ("CU_STAT*"));
+ }
+}
+
+/*
+ * SAAL-RELEASE.confirm
+ */
+static void
+coord_saal_release_confirm(struct uni *uni)
+{
+ switch (uni->custat) {
+
+ case CU_STAT0:
+ case CU_STAT1:
+ case CU_STAT3:
+ VERBOSE0(uni, UNI_FAC_COORD,
+ "signal saal_release.confirm in CU%u", uni->custat);
+ break;
+
+ case CU_STAT2:
+ /*
+ * Q.2931:Coord-U 5/10
+ */
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_LINK_RELEASE_confirm, 0, NULL);
+ set_custat(uni, CU_STAT0);
+ break;
+
+ default:
+ ASSERT(0, ("CU_STAT*"));
+ }
+}
+
+/*
+ * SAAL failure.
+ */
+static void
+coord_saal_release_indication(struct uni *uni)
+{
+ switch (uni->custat) {
+
+ case CU_STAT0:
+ case CU_STAT2:
+ VERBOSE0(uni, UNI_FAC_COORD,
+ "signal saal_release.indication in CU%u", uni->custat);
+ break;
+
+ case CU_STAT1:
+ case CU_STAT3:
+ /*
+ * Q.2931:Coord-U 4/10
+ * Q.2931:Coord-U 5/10
+ */
+ sig_all_calls(uni, SIGC_LINK_RELEASE_indication);
+ set_custat(uni, CU_STAT0);
+ break;
+
+ default:
+ ASSERT(0, ("CU_STAT*"));
+ }
+}
+
+/*
+ * Link-establish.request from USER. This can also come from
+ * a call instance. In this case 'cookie' is zero.
+ */
+static void
+coord_link_establish_request(struct uni *uni, uint32_t cookie)
+{
+ switch (uni->custat) {
+
+ case CU_STAT0:
+ /*
+ * Q.2931:Coord-U 4/10
+ */
+ uni->funcs->saal_output(uni, uni->arg,
+ SAAL_ESTABLISH_request, NULL);
+ if (!TIMER_ISACT(uni, t309))
+ TIMER_START_UNI(uni, t309, uni->timer309);
+ set_custat(uni, CU_STAT1);
+ if (cookie)
+ uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
+ break;
+
+ case CU_STAT1:
+ /*
+ * Q.2931:Coord-U 4/10
+ * This is probably missing from the delay field.
+ */
+ uni_delenq_coord(uni, SIGO_LINK_ESTABLISH_request,
+ cookie, NULL);
+ break;
+
+ case CU_STAT2:
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
+ if (cookie == 0)
+ VERBOSE0(uni, UNI_FAC_COORD,
+ "signal link-establish.request in CU%u",
+ uni->custat);
+ break;
+
+ case CU_STAT3:
+ /*
+ * Q.2931:Coord-U 5/10
+ */
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_LINK_ESTABLISH_confirm, 0, NULL);
+ uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
+ break;
+
+ default:
+ ASSERT(0, ("CU_STAT*"));
+ }
+}
+
+/*
+ * Link-release.request from user
+ */
+static void
+coord_link_release_request(struct uni *uni, u_int cookie)
+{
+ switch (uni->custat) {
+
+ case CU_STAT0:
+ case CU_STAT1:
+ case CU_STAT2:
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
+ break;
+
+ case CU_STAT3:
+ /*
+ * Q.2931:Coord-U 5/10
+ */
+ uni->funcs->saal_output(uni, uni->arg,
+ SAAL_RELEASE_request, NULL);
+ set_custat(uni, CU_STAT2);
+ uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
+ break;
+
+ default:
+ ASSERT(0, ("CU_STAT*"));
+ }
+}
+
+/*
+ * T309 timeout signal
+ */
+static void
+coord_t309(struct uni *uni)
+{
+ switch (uni->custat) {
+
+ case CU_STAT0:
+ case CU_STAT1:
+ /*
+ * Q.2931:Coord-U 4/10
+ */
+ sig_all_calls(uni, SIGC_LINK_ESTABLISH_ERROR_indication);
+ set_custat(uni, CU_STAT0);
+ /* this is not in the SDLs, but how will the call control
+ * know, that starting the LINK has failed otherwise? */
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_LINK_RELEASE_confirm, 0, NULL);
+ break;
+
+ case CU_STAT2:
+ case CU_STAT3:
+ VERBOSE0(uni, UNI_FAC_COORD,
+ "signal T309 in CU%u", uni->custat);
+ break;
+
+ default:
+ ASSERT(0, ("CU_STAT*"));
+ }
+}
+
+/*
+ * Message from SAAL
+ */
+static void
+coord_saal_data_indication(struct uni *uni, struct uni_msg *m)
+{
+ struct uni_all *u;
+ struct call *c;
+
+ memset(&uni->cause, 0, sizeof(uni->cause));
+ if ((u = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(m);
+ return;
+ }
+ if (uni_decode_head(m, u, &uni->cx)) {
+ VERBOSE(uni, UNI_FAC_COORD, 2, "bogus message - ignored");
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+ if (u->u.hdr.cref.cref == CREF_DUMMY) {
+ if (uni->cx.q2932) {
+ input_dummy(uni, m, u);
+ } else {
+ VERBOSE(uni, UNI_FAC_COORD, 2, "dummy cref - ignored");
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+ }
+ return;
+ }
+
+ if (u->u.hdr.cref.cref == CREF_GLOBAL)
+ input_global(uni, m, u);
+ else if ((c = uni_find_call(uni, &u->u.hdr.cref)) == NULL)
+ input_unknown(uni, m, u);
+ else if (c->type == CALL_COBI)
+ input_cobi(c, m, u);
+ else
+ input_call(c, m, u);
+}
+
+/*
+ * Message with global call reference
+ *
+ * Q.2931:Coord-U (X) 7/10
+ */
+static void
+input_global(struct uni *uni, struct uni_msg *m, struct uni_all *u)
+{
+ VERBOSE(uni, UNI_FAC_COORD, 2, "GLOB MTYPE = %x", u->mtype);
+
+ switch (u->mtype) {
+
+ default:
+ /*
+ * Q.2931:Coord-U 7/10
+ * Q.2931: 5.6.3.2e
+ * Amd4: 29e
+ */
+ uni_respond_status(uni, &u->u.hdr.cref,
+ u->u.hdr.cref.flag ? uni->glob_start : uni->glob_respond,
+ UNI_CAUSE_CREF_INV);
+ break;
+
+ case UNI_RESTART:
+ if (u->u.hdr.cref.flag) {
+ /*
+ * Q.2931:Coord-U 7/10 (5.6.3.2h)
+ */
+ uni_respond_status(uni, &u->u.hdr.cref,
+ uni->glob_start, UNI_CAUSE_CREF_INV);
+ break;
+ }
+ uni_enq_resp(uni, SIGR_RESTART, 0, m, u);
+ return;
+
+ case UNI_RESTART_ACK:
+ if (!u->u.hdr.cref.flag) {
+ /*
+ * Q.2931:Coord-U 7/10 (5.6.3.2h)
+ * Note, that the SDL diagram contains an error.
+ * The error with the 'YES' label should go to the
+ * box below 'OTHER'.
+ */
+ uni_respond_status(uni, &u->u.hdr.cref,
+ uni->glob_respond, UNI_CAUSE_CREF_INV);
+ break;
+ }
+ uni_enq_start(uni, SIGS_RESTART_ACK, 0, m, u);
+ return;
+
+ case UNI_STATUS:
+ if (u->u.hdr.cref.flag)
+ uni_enq_start(uni, SIGS_STATUS, 0, m, u);
+ else
+ uni_enq_resp(uni, SIGR_STATUS, 0, m, u);
+ return;
+ }
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * Q.2931:Coord-U 8/10
+ *
+ * Message for an unknown call reference
+ */
+static void
+input_unknown(struct uni *uni, struct uni_msg *m, struct uni_all *u)
+{
+ struct uni_all *resp;
+ struct call *c;
+ u_int cause = UNI_CAUSE_CREF_INV;
+
+ VERBOSE(uni, UNI_FAC_COORD, 2, "UNKNOWN MTYPE = %x", u->mtype);
+
+ switch (u->mtype) {
+
+ default:
+ /*
+ * This message type is entirly unknown
+ *
+ * 5.6.4 and 5.7.1 are only when the call is not in the
+ * NULL state. This means, 5.6.3.2a takes over.
+ */
+ break;
+
+ case UNI_SETUP:
+ if (u->u.hdr.cref.flag)
+ /*
+ * 5.6.3.2c
+ */
+ goto drop;
+ if ((c = uni_create_call(uni, u->u.hdr.cref.cref, 0, 0)) != NULL) {
+ uni_enq_call(c, SIGC_SETUP, 0, m, u);
+ return;
+ }
+ goto drop;
+
+ case UNI_RELEASE_COMPL:
+ /*
+ * 5.6.3.2c
+ */
+ goto drop;
+
+ case UNI_STATUS:
+ /*
+ * 5.6.12
+ *
+ * The SDLs don't use the verify procedure and don't
+ * handle the case of an invalid callstate - we
+ * ignore the message, if the callstate is not good.
+ */
+ (void)uni_decode_body(m, u, &uni->cx);
+ if (!IE_ISGOOD(u->u.status.callstate))
+ goto drop;
+ if (u->u.status.callstate.state == UNI_CALLSTATE_U0)
+ goto drop;
+ cause = UNI_CAUSE_MSG_INCOMP;
+ break;
+
+ case UNI_STATUS_ENQ:
+ if ((resp = UNI_ALLOC()) == NULL)
+ goto drop;
+
+ (void)uni_decode_body(m, u, &uni->cx);
+ MK_MSG_RESP(resp, UNI_STATUS, &u->u.hdr.cref);
+ MK_IE_CALLSTATE(resp->u.status.callstate, UNI_CALLSTATE_U0);
+ MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_STATUS);
+
+ if (IE_ISGOOD(u->u.status_enq.epref)) {
+ /* reflect epref as required by L3MU_PO */
+ resp->u.status.epref = u->u.status_enq.epref;
+ MK_IE_EPREF(resp->u.status.epref,
+ u->u.status_enq.epref.epref,
+ !u->u.status_enq.epref.flag);
+ MK_IE_EPSTATE(resp->u.status.epstate, UNI_EPSTATE_NULL);
+ }
+
+ (void)uni_send_output(resp, uni);
+
+ UNI_FREE(resp);
+ goto drop;
+
+ case UNI_COBISETUP:
+ if (u->u.hdr.cref.flag)
+ /*
+ * 5.6.3.2c (probably)
+ */
+ goto drop;
+ if ((c = uni_create_call(uni, u->u.hdr.cref.cref, 0, 0)) != NULL) {
+ uni_enq_call(c, SIGC_COBISETUP, 0, m, u);
+ return;
+ }
+ goto drop;
+ }
+
+ /*
+ * 5.6.3.2a)
+ *
+ * Respond with a RELEASE COMPLETE
+ */
+ if ((resp = UNI_ALLOC()) == NULL)
+ goto drop;
+
+ MK_MSG_RESP(resp, UNI_RELEASE_COMPL, &u->u.hdr.cref);
+ MK_IE_CAUSE(resp->u.release_compl.cause[0], UNI_CAUSE_LOC_USER, cause);
+ if (uni_diag(cause, UNI_CODING_ITU) == UNI_DIAG_MTYPE)
+ ADD_CAUSE_MTYPE(resp->u.release_compl.cause[0], u->mtype);
+
+ (void)uni_send_output(resp, uni);
+
+ UNI_FREE(resp);
+
+ drop:
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+}
+
+static void
+input_cobi(struct call *c __unused, struct uni_msg *m, struct uni_all *u)
+{
+ /* XXX */
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+}
+
+static void
+input_dummy(struct uni *uni __unused, struct uni_msg *m, struct uni_all *u)
+{
+ /* XXX */
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+}
+
+static void
+input_call(struct call *c, struct uni_msg *m, struct uni_all *u)
+{
+ VERBOSE(c->uni, UNI_FAC_COORD, 2, "CALL MTYPE = %x %d/%s",
+ u->mtype, c->cref, c->mine ? "mine":"his");
+
+ switch (u->mtype) {
+
+ case UNI_SETUP:
+ /*
+ * Ignored
+ */
+ break;
+
+ case UNI_CALL_PROC:
+ uni_enq_call(c, SIGC_CALL_PROC, 0, m, u);
+ return;
+
+ case UNI_ALERTING:
+ uni_enq_call(c, SIGC_ALERTING, 0, m, u);
+ return;
+
+ case UNI_RELEASE:
+ uni_enq_call(c, SIGC_RELEASE, 0, m, u);
+ return;
+
+ case UNI_RELEASE_COMPL:
+ uni_enq_call(c, SIGC_RELEASE_COMPL, 0, m, u);
+ return;
+
+ case UNI_CONNECT:
+ uni_enq_call(c, SIGC_CONNECT, 0, m, u);
+ return;
+
+ case UNI_CONNECT_ACK:
+ uni_enq_call(c, SIGC_CONNECT_ACK, 0, m, u);
+ return;
+
+ case UNI_NOTIFY:
+ uni_enq_call(c, SIGC_NOTIFY, 0, m, u);
+ return;
+
+ case UNI_STATUS:
+ uni_enq_call(c, SIGC_STATUS, 0, m, u);
+ return;
+
+ case UNI_STATUS_ENQ:
+ uni_enq_call(c, SIGC_STATUS_ENQ, 0, m, u);
+ return;
+
+ case UNI_ADD_PARTY:
+ uni_enq_call(c, SIGC_ADD_PARTY, 0, m, u);
+ return;
+
+ case UNI_PARTY_ALERTING:
+ uni_enq_call(c, SIGC_PARTY_ALERTING, 0, m, u);
+ return;
+
+ case UNI_ADD_PARTY_ACK:
+ uni_enq_call(c, SIGC_ADD_PARTY_ACK, 0, m, u);
+ return;
+
+ case UNI_ADD_PARTY_REJ:
+ uni_enq_call(c, SIGC_ADD_PARTY_REJ, 0, m, u);
+ return;
+
+ case UNI_DROP_PARTY:
+ uni_enq_call(c, SIGC_DROP_PARTY, 0, m, u);
+ return;
+
+ case UNI_DROP_PARTY_ACK:
+ uni_enq_call(c, SIGC_DROP_PARTY_ACK, 0, m, u);
+ return;
+
+ default:
+ uni_enq_call(c, SIGC_UNKNOWN, 0, m, u);
+ return;
+ }
+ UNI_FREE(u);
+ uni_msg_destroy(m);
+}
+
+
+/*
+ * This macro tries to implement the delaying behaviour for
+ * message from the API when we are in the Awaiting-Establish state.
+ * In this state, the message is delayed. If we drop back to CU 0,
+ * everything gets unqueued and errors are returned for all that stuff.
+ * If we progess to CUSTAT2 we process the requests.
+ */
+#define COMMON_DELAY(SIG, COOKIE) \
+ if (uni->custat == CU_STAT0 || uni->custat == CU_STAT2) {\
+ uniapi_uni_error(uni, UNIAPI_ERROR_BADCU, \
+ COOKIE, 0); \
+ break; \
+ } \
+ if (uni->custat == CU_STAT1) { \
+ uni_delenq_coord(uni, SIG, COOKIE, msg); \
+ break; \
+ }
+
+/*
+ * Signal handler of the coordinator
+ */
+void
+uni_sig_coord(struct uni *uni, enum coord_sig sig, uint32_t cookie,
+ struct uni_msg *msg)
+{
+ struct call *c;
+
+ if (sig >= SIGO_END) {
+ VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to "
+ "Coord", sig);
+ if (msg)
+ uni_msg_destroy(msg);
+ return;
+ }
+
+ VERBOSE(uni, UNI_FAC_COORD, 1, "Signal %s in state %s",
+ coord_sigs[sig], cunames[uni->custat]);
+
+ switch (sig) {
+
+ case SIGO_END:
+ break;
+
+ case SIGO_DATA: /* delayed output */
+ if (uni->custat == CU_STAT0 || uni->custat == CU_STAT1)
+ break; /* drop */
+ if (uni->custat == CU_STAT1)
+ uni_delenq_coord(uni, SIGO_DATA, cookie, msg);/* ??? */
+ else
+ uni->funcs->saal_output(uni, uni->arg,
+ SAAL_DATA_request, msg);
+ msg = NULL;
+ break;
+
+ /*
+ * SAAL signals
+ */
+ case SIGO_SAAL_ESTABLISH_indication:
+ coord_saal_establish_indication(uni);
+ break;
+
+ case SIGO_SAAL_ESTABLISH_confirm:
+ coord_saal_establish_confirm(uni);
+ break;
+
+ case SIGO_SAAL_RELEASE_confirm:
+ coord_saal_release_confirm(uni);
+ break;
+
+ case SIGO_SAAL_RELEASE_indication:
+ coord_saal_release_indication(uni);
+ break;
+
+ case SIGO_SAAL_DATA_indication:
+ coord_saal_data_indication(uni, msg);
+ msg = NULL;
+ break;
+
+ case SIGO_SAAL_UDATA_indication:
+ VERBOSE0(uni, UNI_FAC_ERR, "SAAL_UDATA_indication");
+ break;
+
+ /*
+ * Signals from USER
+ */
+ case SIGO_LINK_ESTABLISH_request:
+ coord_link_establish_request(uni, cookie);
+ break;
+
+ case SIGO_LINK_RELEASE_request:
+ coord_link_release_request(uni, cookie);
+ break;
+
+ case SIGO_RESET_request:
+ uni_enq_start(uni, SIGS_RESET_request, cookie, msg, NULL);
+ msg = NULL;
+ if (uni->custat == CU_STAT0) {
+ uni->funcs->saal_output(uni, uni->arg,
+ SAAL_ESTABLISH_request, NULL);
+ if (!TIMER_ISACT(uni, t309))
+ TIMER_START_UNI(uni, t309, uni->timer309);
+ set_custat(uni, CU_STAT1);
+ }
+ break;
+
+ case SIGO_RESET_ERROR_response:
+ COMMON_DELAY(SIGO_RESET_ERROR_response, cookie);
+ uni_enq_resp(uni, SIGR_RESET_ERROR_response, cookie, msg, NULL);
+ msg = NULL;
+ break;
+
+ case SIGO_RESET_response:
+ COMMON_DELAY(SIGO_RESET_response, cookie);
+ uni_enq_resp(uni, SIGR_RESET_response, cookie, msg, NULL);
+ msg = NULL;
+ break;
+
+ case SIGO_SETUP_request:
+ if ((c = uni_create_new_call(uni, cookie)) != NULL) {
+ uni_enq_call(c, SIGC_SETUP_request, cookie, msg, NULL);
+ msg = NULL;
+ if (uni->custat == CU_STAT0) {
+ uni->funcs->saal_output(uni, uni->arg,
+ SAAL_ESTABLISH_request, NULL);
+ if (!TIMER_ISACT(uni, t309))
+ TIMER_START_UNI(uni, t309, uni->timer309);
+ set_custat(uni, CU_STAT1);
+ }
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+
+ case SIGO_PROCEEDING_request:
+ {
+ struct uniapi_proceeding_request *arg =
+ uni_msg_rptr(msg, struct uniapi_proceeding_request *);
+
+ COMMON_DELAY(SIGO_PROCEEDING_request, cookie);
+ if ((c = uni_find_call(uni, &arg->call_proc.hdr.cref)) != NULL) {
+ uni_enq_call(c, SIGC_PROCEEDING_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_ALERTING_request:
+ {
+ struct uniapi_alerting_request *arg =
+ uni_msg_rptr(msg, struct uniapi_alerting_request *);
+
+ COMMON_DELAY(SIGO_ALERTING_request, cookie);
+ if ((c = uni_find_call(uni, &arg->alerting.hdr.cref)) != NULL) {
+ uni_enq_call(c, SIGC_ALERTING_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_SETUP_response:
+ {
+ struct uniapi_setup_response *arg =
+ uni_msg_rptr(msg, struct uniapi_setup_response *);
+
+ COMMON_DELAY(SIGO_SETUP_response, cookie);
+ if ((c = uni_find_call(uni, &arg->connect.hdr.cref)) != NULL) {
+ uni_enq_call(c, SIGC_SETUP_response, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_SETUP_COMPLETE_request:
+ {
+ struct uniapi_setup_complete_request *arg =
+ uni_msg_rptr(msg, struct uniapi_setup_complete_request *);
+
+ COMMON_DELAY(SIGO_SETUP_COMPLETE_request, cookie);
+ if ((c = uni_find_call(uni, &arg->connect_ack.hdr.cref)) != NULL) {
+ uni_enq_call(c, SIGC_SETUP_COMPLETE_request,
+ cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_RELEASE_request:
+ {
+ struct uniapi_release_request *arg =
+ uni_msg_rptr(msg, struct uniapi_release_request *);
+
+ COMMON_DELAY(SIGO_RELEASE_request, cookie);
+ if ((c = uni_find_call(uni, &arg->release.hdr.cref)) != NULL) {
+ uni_enq_call(c, SIGC_RELEASE_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_RELEASE_response:
+ {
+ struct uniapi_release_response *arg =
+ uni_msg_rptr(msg, struct uniapi_release_response *);
+
+ COMMON_DELAY(SIGO_RELEASE_response, cookie);
+ if ((c = uni_find_call(uni, &arg->release_compl.hdr.cref)) != NULL) {
+ uni_enq_call(c, SIGC_RELEASE_response, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_NOTIFY_request:
+ {
+ struct uniapi_notify_request *arg =
+ uni_msg_rptr(msg, struct uniapi_notify_request *);
+
+ COMMON_DELAY(SIGO_NOTIFY_request, cookie);
+ if ((c = uni_find_call(uni, &arg->notify.hdr.cref)) != NULL) {
+ uni_enq_call(c, SIGC_NOTIFY_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_STATUS_ENQUIRY_request:
+ {
+ struct uniapi_status_enquiry_request *arg =
+ uni_msg_rptr(msg, struct uniapi_status_enquiry_request *);
+
+ COMMON_DELAY(SIGO_STATUS_ENQUIRY_request, cookie);
+ if ((c = uni_find_call(uni, &arg->cref)) != NULL) {
+ uni_enq_call(c, SIGC_STATUS_ENQUIRY_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_ADD_PARTY_request:
+ {
+ struct uniapi_add_party_request *arg =
+ uni_msg_rptr(msg, struct uniapi_add_party_request *);
+
+ COMMON_DELAY(SIGO_ADD_PARTY_request, cookie);
+ if ((c = uni_find_call(uni, &arg->add.hdr.cref)) != NULL) {
+ if (c->type != CALL_ROOT) {
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
+ cookie);
+ break;
+ }
+ uni_enq_call(c, SIGC_ADD_PARTY_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_PARTY_ALERTING_request:
+ {
+ struct uniapi_party_alerting_request *arg =
+ uni_msg_rptr(msg, struct uniapi_party_alerting_request *);
+
+ COMMON_DELAY(SIGO_PARTY_ALERTING_request, cookie);
+ if ((c = uni_find_call(uni, &arg->alert.hdr.cref)) != NULL) {
+ if (c->type != CALL_LEAF) {
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
+ cookie);
+ break;
+ }
+ uni_enq_call(c, SIGC_PARTY_ALERTING_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_ADD_PARTY_ACK_request:
+ {
+ struct uniapi_add_party_ack_request *arg =
+ uni_msg_rptr(msg, struct uniapi_add_party_ack_request *);
+
+ COMMON_DELAY(SIGO_ADD_PARTY_ACK_request, cookie);
+ if ((c = uni_find_call(uni, &arg->ack.hdr.cref)) != NULL) {
+ if (c->type != CALL_LEAF) {
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
+ cookie);
+ break;
+ }
+ uni_enq_call(c, SIGC_ADD_PARTY_ACK_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_ADD_PARTY_REJ_request:
+ {
+ struct uniapi_add_party_rej_request *arg =
+ uni_msg_rptr(msg, struct uniapi_add_party_rej_request *);
+
+ COMMON_DELAY(SIGO_ADD_PARTY_REJ_request, cookie);
+ if ((c = uni_find_call(uni, &arg->rej.hdr.cref)) != NULL) {
+ if (c->type != CALL_LEAF) {
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
+ cookie);
+ break;
+ }
+ uni_enq_call(c, SIGC_ADD_PARTY_REJ_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_DROP_PARTY_request:
+ {
+ struct uniapi_drop_party_request *arg =
+ uni_msg_rptr(msg, struct uniapi_drop_party_request *);
+
+ COMMON_DELAY(SIGO_DROP_PARTY_request, cookie);
+ if ((c = uni_find_call(uni, &arg->drop.hdr.cref)) != NULL) {
+ if (c->type != CALL_ROOT && c->type != CALL_LEAF) {
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
+ cookie);
+ break;
+ }
+ uni_enq_call(c, SIGC_DROP_PARTY_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_DROP_PARTY_ACK_request:
+ {
+ struct uniapi_drop_party_ack_request *arg =
+ uni_msg_rptr(msg, struct uniapi_drop_party_ack_request *);
+
+ COMMON_DELAY(SIGO_DROP_PARTY_ACK_request, cookie);
+ if ((c = uni_find_call(uni, &arg->ack.hdr.cref)) != NULL) {
+ if (c->type != CALL_ROOT && c->type != CALL_LEAF) {
+ uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
+ cookie);
+ break;
+ }
+ uni_enq_call(c, SIGC_DROP_PARTY_ACK_request, cookie, msg, NULL);
+ msg = NULL;
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ case SIGO_ABORT_CALL_request:
+ {
+ struct uniapi_abort_call_request *arg =
+ uni_msg_rptr(msg, struct uniapi_abort_call_request *);
+
+ if ((c = uni_find_call(uni, &arg->cref)) != NULL) {
+ uni_enq_call(c, SIGC_ABORT_CALL_request, cookie, NULL, NULL);
+ } else {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
+ UNI_CALLSTATE_U0);
+ }
+ break;
+ }
+
+ /*
+ * Call-Control
+ */
+ case SIGO_CALL_DESTROYED:
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_CALL_DESTROYED, 0, msg);
+ msg = NULL;
+ break;
+
+ /*
+ * ResetRespond
+ */
+ case SIGO_RESET_indication:
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_RESET_indication, 0, msg);
+ msg = NULL;
+ break;
+
+ /*
+ * Timeouts
+ */
+ case SIGO_T309:
+ coord_t309(uni);
+ break;
+
+ }
+ if (msg != NULL)
+ uni_msg_destroy(msg);
+}
+
+/*
+ * Send a signal to all call instances
+ */
+static void
+sig_all_calls(struct uni *uni, u_int sig)
+{
+ struct call *call;
+
+ TAILQ_FOREACH(call, &uni->calls, link)
+ uni_enq_call(call, sig, 0, NULL, NULL);
+}
+
+/*
+ * Set a new coordinator state - this moves all delayed coordinator
+ * signals from the delayed queue to the signal queue.
+ */
+static int
+cufilt(struct sig *s, void *arg __unused)
+{
+ return (s->type == SIG_COORD);
+}
+
+static void
+set_custat(struct uni *uni, enum cu_stat nstate)
+{
+ if (uni->custat != nstate) {
+ uni->custat = nstate;
+ uni_undel(uni, cufilt, NULL);
+ }
+}
+
+/*
+ * T309 timeout function
+ */
+static void
+t309_func(struct uni *uni)
+{
+ uni_enq_coord(uni, SIGO_T309, 0, NULL);
+}
+
+/*
+ * Respond with a status message
+ */
+void
+uni_respond_status(struct uni *uni, struct uni_cref *cref,
+ enum uni_callstate cs, enum uni_cause c1)
+{
+ struct uni_all *resp;
+
+ if ((resp = UNI_ALLOC()) == NULL)
+ return;
+
+ MK_MSG_RESP(resp, UNI_STATUS, cref);
+ MK_IE_CALLSTATE(resp->u.status.callstate, cs);
+ MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, c1);
+
+ (void)uni_send_output(resp, uni);
+
+ UNI_FREE(resp);
+}
+
+/*
+ * Respond with a status message
+ */
+void
+uni_respond_status_mtype(struct uni *uni, struct uni_cref *cref,
+ enum uni_callstate cs, enum uni_cause c1, u_int mtype)
+{
+ struct uni_all *resp;
+
+ if((resp = UNI_ALLOC()) == NULL)
+ return;
+
+ MK_MSG_RESP(resp, UNI_STATUS, cref);
+ MK_IE_CALLSTATE(resp->u.status.callstate, cs);
+ MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, c1);
+ ADD_CAUSE_MTYPE(resp->u.status.cause, mtype);
+
+ (void)uni_send_output(resp, uni);
+
+ UNI_FREE(resp);
+}
+
+/*
+ * Send a message. If we are in CUSTAT1, delay the message if we
+ * are in CUSTAT3 send it, else drop it.
+ */
+int
+uni_send_output(struct uni_all *u, struct uni *uni)
+{
+ struct uni_msg *m;
+ int err;
+
+ if (uni->custat == CU_STAT0 || uni->custat == CU_STAT2)
+ return (0);
+
+ m = uni_msg_alloc(1024);
+ if ((err = uni_encode(m, u, &uni->cx)) != 0) {
+ VERBOSE0(uni, UNI_FAC_ERR, "uni_encode failed: %08x", err);
+ uni_msg_destroy(m);
+ return (-1);
+ }
+ if (uni->custat == CU_STAT1)
+ uni_delenq_coord(uni, SIGO_DATA, 0, m);
+ else
+ uni->funcs->saal_output(uni, uni->arg, SAAL_DATA_request, m);
+ return (0);
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_party.c b/sys/contrib/ngatm/netnatm/sig/sig_party.c
new file mode 100644
index 000000000000..f9d5cd0cf571
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/sig_party.c
@@ -0,0 +1,1353 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/sig_party.c,v 1.18 2004/08/05 07:11:01 brandt Exp $
+ *
+ * Party instance handling
+ */
+
+#include <netnatm/unimsg.h>
+#include <netnatm/saal/sscfudef.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/sig/uni.h>
+
+#include <netnatm/sig/unipriv.h>
+#include <netnatm/sig/unimkmsg.h>
+#include <netnatm/sig/unimsgcpy.h>
+
+static void drop_partyE(struct party *p);
+static int epstate_compat(struct party *, enum uni_epstate);
+
+#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME,
+static const char *const party_sigs[] = {
+ DEF_PARTY_SIGS
+};
+#undef DEF_PRIV_SIG
+
+TIMER_FUNC_PARTY(t397, t397_func)
+TIMER_FUNC_PARTY(t398, t398_func)
+TIMER_FUNC_PARTY(t399, t399_func)
+
+static __inline void
+set_party_state(struct party *p, enum uni_epstate state)
+{
+ if (p->state != state) {
+ VERBOSE(p->call->uni, UNI_FAC_CALL, 1,
+ "party %u/%u %u/%u PU%u -> PU%u",
+ p->call->cref, p->call->mine,
+ p->epref, p->flags & PARTY_MINE, p->state, state);
+ p->state = state;
+ }
+}
+
+/*
+ * Create a party with a given endpoint reference.
+ * 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, uint32_t cookie)
+{
+ struct party *p;
+ struct uni_msg *api;
+ struct uniapi_party_created *ind;
+
+ mine = (mine ? PARTY_MINE : 0);
+
+ if ((p = PARTY_ALLOC()) == NULL)
+ return (NULL);
+
+ if ((ind = ALLOC_API(struct uniapi_party_created, api)) == NULL) {
+ PARTY_FREE(p);
+ return (NULL);
+ }
+
+ ind->cref.cref = c->cref;
+ ind->cref.flag = c->mine;
+ MK_IE_EPREF(ind->epref, epref, mine);
+ ind->epref.h.act = UNI_IEACT_DEFAULT;
+
+ p->call = c;
+ p->epref = epref;
+ p->flags = mine;
+ p->state = UNI_EPSTATE_NULL;;
+
+ TIMER_INIT_PARTY(p, t397);
+ TIMER_INIT_PARTY(p, t398);
+ TIMER_INIT_PARTY(p, t399);
+
+ TAILQ_INSERT_HEAD(&c->parties, p, link);
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_PARTY_CREATED, cookie, api);
+
+ VERBOSE(c->uni, UNI_FAC_CALL, 1, "created party %u/%s %u/%s",
+ p->call->cref, p->call->mine ? "mine" : "his",
+ p->epref, (p->flags & PARTY_MINE) ? "mine" : "his");
+
+ return (p);
+
+}
+
+struct party *
+uni_create_party(struct call *c, struct uni_ie_epref *epref)
+{
+ return (uni_create_partyx(c, epref->epref, epref->flag, 0));
+}
+
+struct party *
+uni_find_party(struct call *c, struct uni_ie_epref *epref)
+{
+ struct party *p;
+
+ TAILQ_FOREACH(p, &c->parties, link)
+ if (p->epref == epref->epref &&
+ (!(p->flags & PARTY_MINE) == !epref->flag))
+ return (p);
+ return (NULL);
+}
+struct party *
+uni_find_partyx(struct call *c, u_int epref, u_int mine)
+{
+ struct party *p;
+
+ TAILQ_FOREACH(p, &c->parties, link)
+ if (p->epref == epref && (!(p->flags & PARTY_MINE) == !mine))
+ return (p);
+ return (NULL);
+}
+
+/*
+ * Destroy a party.
+ * This function is assumed to remove the party from the parent's call
+ * party list.
+ */
+void
+uni_destroy_party(struct party *p, int really)
+{
+ struct uni_msg *api;
+ struct uniapi_party_destroyed *ind;
+
+ TIMER_DESTROY_PARTY(p, t397);
+ TIMER_DESTROY_PARTY(p, t398);
+ TIMER_DESTROY_PARTY(p, t399);
+
+ TAILQ_REMOVE(&p->call->parties, p, link);
+
+ uni_delsig(p->call->uni, SIG_PARTY, p->call, p);
+
+ if (!really) {
+ ind = ALLOC_API(struct uniapi_party_destroyed, api);
+ if (ind != NULL) {
+ ind->cref.cref = p->call->cref;
+ ind->cref.flag = p->call->mine;
+ ind->epref.epref = p->epref;
+ ind->epref.flag = p->flags & PARTY_MINE;
+ ind->epref.h.act = UNI_IEACT_DEFAULT;
+ IE_SETPRESENT(ind->epref);
+
+ uni_enq_call(p->call, SIGC_PARTY_DESTROYED, 0, api, NULL);
+ }
+
+ uni_enq_party(p, SIGP_PARTY_DELETE, 0, NULL, NULL);
+ return;
+ }
+ PARTY_FREE(p);
+}
+
+/*
+ * Count number of parties in active states.
+ * If the argument is 0 only ACTIVE parties are counter
+ * If the argument is 1 only parties in establishing states are counted
+ * If the argument is 2 both are counted.
+ */
+u_int
+uni_party_act_count(struct call *c, int kind)
+{
+ struct party *p;
+ u_int cnt;
+
+ cnt = 0;
+ TAILQ_FOREACH(p, &c->parties, link) {
+ switch (p->state) {
+
+ case UNI_EPSTATE_ACTIVE:
+ if (kind == 0 || kind == 2)
+ cnt++;
+ break;
+
+ case UNI_EPSTATE_ALERT_RCVD:
+ case UNI_EPSTATE_ADD_INIT:
+ case UNI_EPSTATE_ALERT_DLVD:
+ case UNI_EPSTATE_ADD_RCVD:
+ if (kind == 1 || kind == 2)
+ cnt++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return (cnt);
+}
+
+static void
+stop_all_party_timers(struct party *p)
+{
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_STOP_PARTY(p, t398);
+ TIMER_STOP_PARTY(p, t399);
+}
+/************************************************************/
+
+/*
+ * Add-party.request
+ *
+ * Q.2971:Party-control-U 3 (PU0)
+ * Q.2971:Party-control-N 3 (PN0)
+ */
+static void
+pun0_add_party_request(struct party *p, struct uni_msg *api, uint32_t cookie)
+{
+ struct uni_all *add;
+ struct uniapi_add_party_request *req =
+ uni_msg_rptr(api, struct uniapi_add_party_request *);
+
+ if ((add = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+
+ add->u.add_party = req->add;
+ MK_MSG_ORIG(add, UNI_ADD_PARTY, p->call->cref, !p->call->mine);
+ uni_send_output(add, p->call->uni);
+ UNI_FREE(add);
+
+ TIMER_START_PARTY(p, t399, p->call->uni->timer399);
+
+ set_party_state(p, UNI_EPSTATE_ADD_INIT);
+
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * Add-party-ack.request
+ *
+ * Q.2971:Party-Control-U 6 PU2
+ * Q.2971:Party-Control-U 7 PU3
+ * Q.2971:Party-Control-N 6 PN2
+ * Q.2971:Party-Control-N 7 PN3
+ */
+static void
+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 =
+ uni_msg_rptr(m, struct uniapi_add_party_ack_request *);
+
+ if ((ack = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(m);
+ return;
+ }
+ ack->u.add_party_ack = req->ack;
+ MK_MSG_ORIG(ack, UNI_ADD_PARTY_ACK, p->call->cref, !p->call->mine);
+ uni_send_output(ack, p->call->uni);
+ UNI_FREE(ack);
+
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+
+ uni_msg_destroy(m);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * Add-party-rej.request
+ *
+ * Q.2971:Party-Control-U 6 PU2
+ * Q.2971:Party-Control-N 6 PN2
+ */
+static void
+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 =
+ uni_msg_rptr(m, struct uniapi_add_party_rej_request *);
+
+ if ((rej = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(m);
+ return;
+ }
+
+ stop_all_party_timers(p);
+
+ rej->u.add_party_rej = req->rej;
+ MK_MSG_ORIG(rej, UNI_ADD_PARTY_REJ, p->call->cref, !p->call->mine);
+ uni_enq_call(p->call, SIGC_SEND_ADD_PARTY_REJ, cookie, NULL, rej);
+
+ uni_msg_destroy(m);
+ p->state = UNI_EPSTATE_NULL;
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+
+ uni_destroy_party(p, 0);
+}
+
+/*
+ * ADD PARTY in PU0, PN0
+ *
+ * Q.2971:Party-Control-U 3/14 PU0
+ */
+static void
+pun0_add_party(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_add_party_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_add_party_indication, api);
+ if (ind != NULL) {
+ ind->add.hdr = u->u.hdr;
+ copy_msg_add_party(&u->u.add_party, &ind->add);
+ p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
+ UNIAPI_ADD_PARTY_indication, 0, api);
+ }
+ set_party_state(p, UNI_EPSTATE_ADD_RCVD);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * PARTY-ALERTING.request
+ *
+ * Q.2971:Party-Control-U 6 (PU2)
+ * Q.2971:Party-Control-N 6 (PN2)
+ */
+static void
+pun2_party_alerting_request(struct party *p, struct uni_msg *api,
+ uint32_t cookie)
+{
+ struct uni_all *alert;
+ struct uniapi_party_alerting_request *req =
+ uni_msg_rptr(api, struct uniapi_party_alerting_request *);
+
+ if ((alert = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(api);
+ return;
+ }
+ alert->u.party_alerting = req->alert;
+ MK_MSG_ORIG(alert, UNI_PARTY_ALERTING,
+ p->call->cref, !p->call->mine);
+ uni_send_output(alert, p->call->uni);
+ UNI_FREE(alert);
+
+ set_party_state(p, UNI_EPSTATE_ALERT_DLVD);
+
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * PARTY-ALERTING in state PU1/PN1
+ *
+ * Q.2971:Party-Control-U 14
+ * Q.2971:Party-Control-N 5
+ */
+static void
+pun1_party_alerting(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_party_alerting_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_party_alerting_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+ TIMER_STOP_PARTY(p, t399);
+
+ ind->alert.hdr = u->u.hdr;
+ copy_msg_party_alerting(&u->u.party_alerting, &ind->alert);
+
+ p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
+ UNIAPI_PARTY_ALERTING_indication, 0, api);
+
+ TIMER_START_PARTY(p, t397, p->call->uni->timer397);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_party_state(p, UNI_EPSTATE_ALERT_RCVD);
+}
+
+/*
+ * ADD-PARTY-ACK
+ *
+ * Q.2971:Party-Control-U 4 (PU1)
+ * Q.2971:Party-Control-U 7 (PU4)
+ * Q.2971:Party-Control-N 4 (PN1)
+ * Q.2971:Party-Control-N 7 (PN4)
+ */
+static void
+pun1pun4_add_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_add_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_add_party_ack_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ if (p->state == UNI_EPSTATE_ADD_INIT)
+ TIMER_STOP_PARTY(p, t399);
+ else
+ TIMER_STOP_PARTY(p, t397);
+
+ ind->ack.hdr = u->u.hdr;
+ copy_msg_add_party_ack(&u->u.add_party_ack, &ind->ack);
+
+ p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
+ UNIAPI_ADD_PARTY_ACK_indication, 0, api);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+}
+
+/*
+ * ADD-PARTY-REJECT
+ *
+ * Q.2971:Party-Control-U 4 (PU1)
+ * Q.2971:Party-Control-N 4 (PN1)
+ */
+static void
+pun1_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_add_party_rej_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_add_party_rej_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ TIMER_STOP_PARTY(p, t399);
+
+ ind->rej.hdr = u->u.hdr;
+ copy_msg_add_party_rej(&u->u.add_party_rej, &ind->rej);
+ uni_enq_call(p->call, SIGC_ADD_PARTY_REJ_indication, 0, api, NULL);
+
+ uni_destroy_party(p, 0);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * ADD-PARTY-REJECT
+ *
+ * Q.2971:Party-Control-U 10 (PU5)
+ * Q.2971:Party-Control-N 10 (PN5)
+ */
+static void
+pun5_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ ind->drop.hdr = u->u.hdr;
+ COPY_FROM_ADD_REJ(u, &ind->drop);
+ if (IE_ISGOOD(u->u.add_party_rej.crankback))
+ ind->crankback = u->u.add_party_rej.crankback;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL);
+
+ TIMER_STOP_PARTY(p, t398);
+
+ uni_destroy_party(p, 0);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * DROP-PARTY-ACKNOWLEDGE
+ *
+ * Q.2971:Party-Control-U 8
+ * Q.2971:Party-Control-N 8
+ *
+ * Message already verified in Call-Control!
+ */
+static void
+punx_drop_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ stop_all_party_timers(p);
+
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind != NULL) {
+ ind->drop.hdr = u->u.hdr;
+ COPY_FROM_DROP_ACK(u, &ind->drop);
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
+ 0, api, NULL);
+ }
+
+ uni_destroy_party(p, 0);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * DROP PARTY message in any state except PU5/PN5
+ *
+ * Q.2971:Party-Control-U 9
+ * Q.2971:Party-Control-N 9
+ */
+static void
+punx_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_drop_party_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ ind->drop.hdr = u->u.hdr;
+ copy_msg_drop_party(&u->u.drop_party, &ind->drop);
+
+ /* need the cause even if it is bad */
+ if (IE_ISERROR(u->u.drop_party.cause))
+ ind->drop.cause = u->u.drop_party.cause;
+
+ ind->my_cause = p->call->uni->cause;
+
+ uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL);
+
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_STOP_PARTY(p, t399);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_party_state(p, UNI_EPSTATE_DROP_RCVD);
+}
+
+/*
+ * DROP PARTY message in state PU5/PN5
+ *
+ * Q.2971:Party-Control-U 10
+ * Q.2971:Party-Control-N 10
+ */
+static void
+pun5_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ ind->drop.hdr = u->u.hdr;
+ copy_msg_drop_party(&u->u.drop_party, &ind->drop);
+
+ /* need the cause even if it is bad */
+ if (IE_ISERROR(u->u.drop_party.cause))
+ ind->drop.cause = u->u.drop_party.cause;
+
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL);
+
+ TIMER_STOP_PARTY(p, t398);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_party_state(p, UNI_EPSTATE_DROP_RCVD);
+
+ uni_destroy_party(p, 0);
+}
+
+/************************************************************/
+
+/*
+ * T399
+ *
+ * Q.2971:Party-Control-U 4 (PU1)
+ * Q.2971:Party-Control-N 4 (PN1)
+ */
+static void
+pun1_t399(struct party *p)
+{
+ if (p->call->uni->proto == UNIPROTO_UNI40N) {
+ MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_NO_RESPONSE);
+ } else {
+ MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(p->call->uni->cause, "399");
+ }
+
+ drop_partyE(p);
+}
+
+/*
+ * T398
+ *
+ * Q.2971:Party-Control-U 10 (PU5)
+ * Q.2971:Party-Control-N 10 (PN5)
+ */
+static void
+pun5_t398(struct party *p)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_all *drop;
+ struct uni_msg *api;
+
+ MK_IE_CAUSE(p->call->uni->cause,
+ UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(p->call->uni->cause, "398");
+ /*
+ * Send indication to API
+ */
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind != NULL) {
+ ind->drop.hdr.cref.cref = p->call->cref;
+ ind->drop.hdr.cref.flag = p->call->mine;
+ ind->drop.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE);
+ ind->drop.cause = p->call->uni->cause;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
+ 0, api, NULL);
+ }
+
+ /*
+ * Send DROP PARTY ACK
+ */
+ if ((drop = UNI_ALLOC()) != NULL) {
+ MK_MSG_ORIG(drop, UNI_DROP_PARTY_ACK,
+ p->call->cref, !p->call->mine);
+ MK_IE_EPREF(drop->u.drop_party_ack.epref,
+ p->epref, !(p->flags & PARTY_MINE));
+ drop->u.drop_party_ack.cause = p->call->uni->cause;
+ uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, 0, NULL, drop);
+ }
+
+ uni_destroy_party(p, 0);
+}
+
+/*
+ * T397
+ *
+ * Q.2971:Party-Control-U 7 (PU4)
+ * Q.2971:Party-Control-N 7 (PN4)
+ */
+static void
+pun4_t397(struct party *p)
+{
+ MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(p->call->uni->cause, "397");
+
+ drop_partyE(p);
+}
+
+/************************************************************/
+
+/*
+ * Drop a party because of an error condition.
+ * This is label E on page Party-Control-U 8/14.
+ *
+ * It is assumed, that the caller has constructed the cause in
+ * p->call->uni->cause.
+ */
+static void
+drop_partyE(struct party *p)
+{
+ struct uni_msg *api;
+ struct uniapi_drop_party_indication *ind;
+ struct uni_all *drop;
+
+ /*
+ * Send indication to API
+ */
+ if ((ind = ALLOC_API(struct uniapi_drop_party_indication, api)) != NULL) {
+ ind->drop.hdr.cref.cref = p->call->cref;
+ ind->drop.hdr.cref.flag = p->call->mine;
+ ind->drop.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE);
+ ind->drop.cause = p->call->uni->cause;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL);
+ }
+ TIMER_STOP_PARTY(p, t399);
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_START_PARTY(p, t398, p->call->uni->timer398);
+
+ if ((drop = UNI_ALLOC()) != NULL) {
+ drop->u.drop_party.cause = p->call->uni->cause;
+ MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine);
+ MK_IE_EPREF(drop->u.drop_party.epref, p->epref,
+ !(p->flags & PARTY_MINE));
+ uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, 0, NULL, drop);
+ }
+
+ set_party_state(p, UNI_EPSTATE_DROP_INIT);
+}
+
+/*
+ * Drop party request in Px1, Px3, Px4 or Px7
+ *
+ * Q.2971:Party-Control-U 8
+ * Q.2971:Party-Control-N 8
+ */
+static void
+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 *);
+ struct uni_all *drop;
+
+ if ((drop = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(api);
+ return;
+ }
+
+ TIMER_STOP_PARTY(p, t399);
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_START_PARTY(p, t398, p->call->uni->timer398);
+
+ drop->u.drop_party = req->drop;
+ MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine);
+ uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, cookie, NULL, drop);
+
+ set_party_state(p, UNI_EPSTATE_DROP_INIT);
+
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * Drop-party-ack.request in Px6
+ *
+ * Q.2971:Party-Control-U 9
+ * Q.2971:Party-Control-N 9
+ */
+static void
+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 *);
+ struct uni_all *ack;
+
+ if ((ack = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+ ack->u.drop_party_ack = req->ack;
+ MK_MSG_ORIG(ack, UNI_DROP_PARTY_ACK, p->call->cref, !p->call->mine);
+ uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, cookie, NULL, ack);
+
+ stop_all_party_timers(p);
+
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+
+ uni_destroy_party(p, 0);
+}
+/************************************************************/
+/*
+ * Party status enquiry request from API or call-control
+ *
+ * Q.2971:Party-Control-U 12
+ * Q.2971:Party-Control-N 12
+ */
+static void
+punx_status_enquiry_request(struct party *p, uint32_t cookie)
+{
+ struct uni_all *enq;
+
+ if((enq = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+ MK_IE_EPREF(enq->u.status_enq.epref, p->epref,
+ !(p->flags & PARTY_MINE));
+ MK_MSG_ORIG(enq, UNI_STATUS_ENQ, p->call->cref, !p->call->mine);
+ uni_enq_call(p->call, SIGC_SEND_STATUS_ENQ, cookie, NULL, enq);
+
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * STATUS in any state except PU5/PN5
+ *
+ * Q.2971:Party-Control-U 12
+ * Q.2971:Party-Control-N 12
+ */
+static void
+punx_status(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ if (u->u.status.epstate.state == UNI_EPSTATE_NULL) {
+ /* should not happend */
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind != NULL) {
+ ind->drop.hdr = u->u.hdr;
+ ind->drop.cause = u->u.status.cause;
+ ind->drop.epref = u->u.status.epref;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
+ 0, api, NULL);
+ }
+ stop_all_party_timers(p);
+
+ uni_destroy_party(p, 0);
+ } else {
+ if (epstate_compat(p, u->u.status.epstate.state)) {
+ if(u->u.status.cause.cause == UNI_CAUSE_MANDAT ||
+ u->u.status.cause.cause == UNI_CAUSE_MTYPE_NIMPL ||
+ u->u.status.cause.cause == UNI_CAUSE_IE_NIMPL ||
+ u->u.status.cause.cause == UNI_CAUSE_IE_INV) {
+ MK_IE_CAUSE(p->call->uni->cause,
+ UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_UNSPEC);
+ drop_partyE(p);
+ }
+ } else {
+ MK_IE_CAUSE(p->call->uni->cause,
+ UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MSG_INCOMP);
+ drop_partyE(p);
+ }
+ }
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * STATUS in PU5/PN5
+ *
+ * Q.2971:Party-Control-U 10
+ * Q.2971:Party-Control-N 10
+ */
+static void
+pun5_status(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ if (u->u.status.epstate.state == UNI_EPSTATE_NULL) {
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind != NULL) {
+ ind->drop.hdr = u->u.hdr;
+ ind->drop.cause = u->u.status.cause;
+ ind->drop.epref = u->u.status.epref;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
+ 0, api, NULL);
+ }
+ TIMER_STOP_PARTY(p, t398);
+
+ uni_destroy_party(p, 0);
+ }
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/************************************************************/
+
+void
+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) {
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Signal %d outside of range to Party-Control", sig);
+ if (msg)
+ uni_msg_destroy(msg);
+ if (u)
+ UNI_FREE(u);
+ return;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_CALL, 1,
+ "Signal %s in state %u of party %u/%s (call %u/%s in state %s)"
+ "; cookie %u", party_sigs[sig], p->state, p->epref,
+ (p->flags & PARTY_MINE) ? "mine" : "his", p->call->cref,
+ p->call->mine ? "mine" : "his", callstates[p->call->cstate].name,
+ cookie);
+
+ switch (sig) {
+
+ case SIGP_PARTY_DELETE:
+ PARTY_FREE(p);
+ break;
+
+ /*
+ * Messages
+ */
+ case SIGP_SETUP:
+ if (p->state == UNI_EPSTATE_NULL) {
+ /* Q.2971:Call-Control-U 3/13 */
+ /* Q.2971:Call-Control-N 3/13 */
+ set_party_state(p, UNI_EPSTATE_ADD_RCVD);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "SETUP in ps=%u", p->state);
+ break;
+
+ case SIGP_ALERTING:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Call-Control-U 14 */
+ /* Q.2971:Call-Control-N 5 */
+ TIMER_START_PARTY(p, t397, p->call->uni->timer397);
+ set_party_state(p, UNI_EPSTATE_ALERT_RCVD);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "ALERTING in ps=%u", p->state);
+ break;
+
+ case SIGP_CONNECT:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Call-Control-U 4/13 */
+ TIMER_STOP_PARTY(p, t399);
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ if (p->state == UNI_EPSTATE_ALERT_RCVD) {
+ /* Q.2971:Call-Control-U 7/13 */
+ TIMER_STOP_PARTY(p, t397);
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "CONNECT in ps=%u", p->state);
+ break;
+
+ case SIGP_CONNECT_ACK:
+ if (p->state == UNI_EPSTATE_ADD_RCVD ||
+ p->state == UNI_EPSTATE_ALERT_DLVD) {
+ /* Q.2971:Call-Control-U 6/13 */
+ /* Q.2971:Call-Control-U 7/13 */
+ p->flags &= ~PARTY_CONNECT;
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "CONNECT in ps=%u", p->state);
+ break;
+
+ case SIGP_RELEASE:
+ if (p->state == UNI_EPSTATE_DROP_INIT) {
+ /* Q.2971:Party-Control-U 10/14 */
+ /* Q.2971:Party-Control-N 10/14 */
+ TIMER_STOP_PARTY(p, t398);
+ uni_destroy_party(p, 0);
+ break;
+ }
+ /* Q.2971:Party-Control-U 11/14 */
+ /* Q.2971:Party-Control-N 11/14 */
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_STOP_PARTY(p, t399);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_RELEASE_COMPL:
+ /* Q.2971:Party-Control-U 11/14 */
+ /* Q.2971:Party-Control-N 11/14 */
+ stop_all_party_timers(p);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_RELEASE_confirm:
+ /* not in the SDLs */
+ stop_all_party_timers(p);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_RELEASE_request:
+ if (p->state == UNI_EPSTATE_DROP_INIT) {
+ /* Q.2971:Party-Control-U 10 */
+ /* Q.2971:Party-Control-N 10 */
+ uni_destroy_party(p, 0);
+ break;
+ }
+ /* Q.2971:Party-Control-U 11 */
+ /* Q.2971:Party-Control-N 11 */
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_STOP_PARTY(p, t399);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_RELEASE_response:
+ /* Q.2971:Party-Control-U 11 */
+ /* Q.2971:Party-Control-N 11 */
+ stop_all_party_timers(p);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_ADD_PARTY:
+ if (p->state == UNI_EPSTATE_NULL) {
+ /* Q.2971:Party-Control-U 3 PU0 */
+ /* Q.2971:Party-Control-N 3 PN0 */
+ pun0_add_party(p, msg, u);
+ break;
+ }
+ if (p->state == UNI_EPSTATE_ADD_RCVD) {
+ /* Q.2971:Party-Control-U 6 PU2 */
+ /* Q.2971:Party-Control-N 6 PN2 */
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+ }
+ uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party.epref, p->state);
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+
+ case SIGP_PARTY_ALERTING:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Party-Control-U 14 */
+ /* Q.2971:Party-Control-N 5 */
+ pun1_party_alerting(p, msg, u);
+ break;
+ }
+ uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.party_alerting.epref, p->state);
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+
+ case SIGP_ADD_PARTY_ACK:
+ if (p->state == UNI_EPSTATE_ADD_INIT ||
+ p->state == UNI_EPSTATE_ALERT_RCVD) {
+ /* Q.2971:Party-Control-U 4 (PU1) */
+ /* Q.2971:Party-Control-U 7 (PU4) */
+ /* Q.2971:Party-Control-N 4 (PN1) */
+ /* Q.2971:Party-Control-N 7 (PN4) */
+ pun1pun4_add_party_ack(p, msg, u);
+ break;
+ }
+ uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party_ack.epref, p->state);
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+
+ case SIGP_ADD_PARTY_REJ:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Party-Control-U 4 (PU1) */
+ /* Q.2971:Party-Control-N 4 (PN1) */
+ pun1_add_party_rej(p, msg, u);
+ break;
+ }
+ if (p->state == UNI_EPSTATE_DROP_INIT) {
+ /* Q.2971:Party-Control-U 10 (PU5) */
+ /* Q.2971:Party-Control-N 10 (PN5) */
+ pun5_add_party_rej(p, msg, u);
+ break;
+ }
+ uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party_rej.epref, p->state);
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+
+ case SIGP_DROP_PARTY_ACK:
+ /* Q.2971:Party-Control-U 8 */
+ /* Q.2971:Party-Control-N 8 */
+ punx_drop_party_ack(p, msg, u);
+ break;
+
+ case SIGP_DROP_PARTY:
+ if (p->state == UNI_EPSTATE_DROP_INIT)
+ /* Q.2971:Party-Control-U 10 */
+ /* Q.2971:Party-Control-N 10 */
+ pun5_drop_party(p, msg, u);
+ else
+ /* Q.2971:Party-Control-U 9 */
+ /* Q.2971:Party-Control-N 9 */
+ punx_drop_party(p, msg, u);
+ break;
+
+ case SIGP_STATUS:
+ if (p->state == UNI_EPSTATE_DROP_INIT)
+ /* Q.2971:Party-Control-U 10 */
+ /* Q.2971:Party-Control-N 10 */
+ pun5_status(p, msg, u);
+ else
+ /* Q.2971:Party-Control-U 12 */
+ /* Q.2971:Party-Control-N 12 */
+ punx_status(p, msg, u);
+ break;
+
+ /*
+ * User
+ */
+ case SIGP_SETUP_request:
+ if (p->state == UNI_EPSTATE_NULL) {
+ /* Q.2971:Party-Control-U 3 */
+ /* Q.2971:Party-Control-N 3 */
+ set_party_state(p, UNI_EPSTATE_ADD_INIT);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "SETUP.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ break;
+
+ case SIGP_SETUP_response:
+ if (p->state == UNI_EPSTATE_ADD_RCVD ||
+ p->state == UNI_EPSTATE_ALERT_DLVD) {
+ /* Q.2971:Party-Control-N 6 (PN2) */
+ /* Q.2971:Party-Control-N 7 (PN3) */
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "SETUP.response in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ break;
+
+ case SIGP_SETUP_COMPL_request:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Party-Control-N 4 */
+ TIMER_STOP_PARTY(p, t399);
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ if (p->state == UNI_EPSTATE_ALERT_RCVD) {
+ /* Q.2971:Party-Control-N 7 */
+ TIMER_STOP_PARTY(p, t397);
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "SETUP_COMPL.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ break;
+
+ case SIGP_ADD_PARTY_request:
+ if (p->state == UNI_EPSTATE_NULL) {
+ /* Q.2971:Party-control-U 3 (PU0) */
+ /* Q.2971:Party-control-N 3 (PN0) */
+ pun0_add_party_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Add-party.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_ALERTING_request:
+ /* Q.2971:Party-Control-U 6 (PU2) */
+ /* Q.2971:Party-Control-N 6 (PN2) */
+ set_party_state(p, UNI_EPSTATE_ALERT_DLVD);
+ break;
+
+ case SIGP_PARTY_ALERTING_request:
+ if (p->state == UNI_EPSTATE_ADD_RCVD) {
+ /* Q.2971:Party-Control-U 6 (PU2) */
+ /* Q.2971:Party-Control-N 6 (PN2) */
+ pun2_party_alerting_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Party-alerting.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_ADD_PARTY_ACK_request:
+ if (p->state == UNI_EPSTATE_ADD_RCVD ||
+ p->state == UNI_EPSTATE_ALERT_DLVD) {
+ /* Q.2971:Party-Control-U 6 PU2 */
+ /* Q.2971:Party-Control-U 7 PU3 */
+ /* Q.2971:Party-Control-N 6 PN2 */
+ /* Q.2971:Party-Control-N 7 PN3 */
+ punx_add_party_ack_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Add-party-ack.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_ADD_PARTY_REJ_request:
+ if (p->state == UNI_EPSTATE_ADD_RCVD) {
+ /* Q.2971:Party-Control-U 6 PU2 */
+ /* Q.2971:Party-Control-N 6 PN2 */
+ pun2_add_party_rej_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Add-party-rej.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_DROP_PARTY_request:
+ if (p->state == UNI_EPSTATE_ADD_INIT ||
+ p->state == UNI_EPSTATE_ALERT_DLVD ||
+ p->state == UNI_EPSTATE_ALERT_RCVD ||
+ p->state == UNI_EPSTATE_ACTIVE) {
+ /* Q.2971:Party-Control-U 8 */
+ /* Q.2971:Party-Control-N 8 */
+ punx_drop_party_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Drop-party.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_DROP_PARTY_ACK_request:
+ if (p->state == UNI_EPSTATE_DROP_RCVD) {
+ /* Q.2971:Party-Control-U 9 */
+ /* Q.2971:Party-Control-N 9 */
+ pun6_drop_party_ack_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Drop-party-ack.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_STATUS_ENQUIRY_request:
+ /* Q.2971:Party-Control-U 12 */
+ /* Q.2971:Party-Control-N 12 */
+ punx_status_enquiry_request(p, cookie);
+ break;
+
+ /*
+ * Timers
+ */
+ case SIGP_T397:
+ if (p->state == UNI_EPSTATE_ALERT_RCVD) {
+ /* Q.2971:Party-Control-U 7 (PU4) */
+ /* Q.2971:Party-Control-N 7 (PN4) */
+ pun4_t397(p);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "T397 in ps=%u", p->state);
+ break;
+
+ case SIGP_T398:
+ if (p->state == UNI_EPSTATE_DROP_INIT) {
+ /* Q.2971:Party-Control-U 10 (PU5) */
+ /* Q.2971:Party-Control-N 10 (PN5) */
+ pun5_t398(p);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "T398 in ps=%u", p->state);
+ break;
+
+ case SIGP_T399:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Party-Control-U 4 (PU1) */
+ /* Q.2971:Party-Control-N 4 (PN1) */
+ pun1_t399(p);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "T399 in ps=%u", p->state);
+ break;
+
+ case SIGP_END:
+ break;
+ }
+}
+
+static void
+t397_func(struct party *p)
+{
+ uni_enq_party(p, SIGP_T397, 0, NULL, NULL);
+}
+static void
+t398_func(struct party *p)
+{
+ uni_enq_party(p, SIGP_T398, 0, NULL, NULL);
+}
+static void
+t399_func(struct party *p)
+{
+ uni_enq_party(p, SIGP_T399, 0, NULL, NULL);
+}
+
+static int
+epstate_compat(struct party *p, enum uni_epstate state)
+{
+ if (p->state == UNI_EPSTATE_ADD_INIT ||
+ p->state == UNI_EPSTATE_ALERT_RCVD)
+ if (state == UNI_EPSTATE_ADD_INIT ||
+ state == UNI_EPSTATE_ALERT_RCVD)
+ return (0);
+ if (p->state == UNI_EPSTATE_ADD_RCVD ||
+ p->state == UNI_EPSTATE_ALERT_DLVD)
+ if (state == UNI_EPSTATE_ADD_RCVD ||
+ state == UNI_EPSTATE_ALERT_DLVD)
+ return (0);
+ return (1);
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_print.c b/sys/contrib/ngatm/netnatm/sig/sig_print.c
new file mode 100644
index 000000000000..af996128e7ea
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/sig_print.c
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) 2002-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ * Kendy Kutzner <kutzner@fokus.fraunhofer.de>
+ *
+ * $Begemot: libunimsg/netnatm/sig/sig_print.c,v 1.6 2004/08/05 07:11:02 brandt Exp $
+ */
+
+#include <sys/types.h>
+#ifdef _KERNEL
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/libkern.h>
+#include <machine/stdarg.h>
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#endif
+
+#include <netnatm/saal/sscfu.h>
+#include <netnatm/msg/uni_hdr.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/msg/uniprint.h>
+#include <netnatm/sig/uni.h>
+#include <netnatm/sig/unisig.h>
+#include <netnatm/sig/unidef.h>
+
+const char *
+uni_strerr(u_int err)
+{
+ static const char *const errstr[] = {
+#define DEF(NAME, VAL, STR) [UNIAPI_##NAME] = STR,
+UNIAPI_DEF_ERRORS(DEF)
+#undef DEF
+ };
+ static char buf[100];
+
+ if (err >= sizeof(errstr)/sizeof(errstr[0]) || errstr[err] == NULL) {
+ sprintf(buf, "Unknown error %u", err);
+ return (buf);
+ }
+ return (errstr[err]);
+}
+
+#define D(M) [M] = #M
+static const char *const msgs[] = {
+ D(UNIAPI_ERROR),
+ D(UNIAPI_CALL_CREATED),
+ D(UNIAPI_CALL_DESTROYED),
+ D(UNIAPI_PARTY_CREATED),
+ D(UNIAPI_PARTY_DESTROYED),
+ D(UNIAPI_LINK_ESTABLISH_request),
+ D(UNIAPI_LINK_ESTABLISH_confirm),
+ D(UNIAPI_LINK_RELEASE_request),
+ D(UNIAPI_LINK_RELEASE_confirm),
+ D(UNIAPI_RESET_request),
+ D(UNIAPI_RESET_confirm),
+ D(UNIAPI_RESET_indication),
+ D(UNIAPI_RESET_ERROR_indication),
+ D(UNIAPI_RESET_response),
+ D(UNIAPI_RESET_ERROR_response),
+ D(UNIAPI_RESET_STATUS_indication),
+ D(UNIAPI_SETUP_request),
+ D(UNIAPI_SETUP_indication),
+ D(UNIAPI_SETUP_response),
+ D(UNIAPI_SETUP_confirm),
+ D(UNIAPI_SETUP_COMPLETE_indication),
+ D(UNIAPI_SETUP_COMPLETE_request),
+ D(UNIAPI_ALERTING_request),
+ D(UNIAPI_ALERTING_indication),
+ D(UNIAPI_PROCEEDING_request),
+ D(UNIAPI_PROCEEDING_indication),
+ D(UNIAPI_RELEASE_request),
+ D(UNIAPI_RELEASE_indication),
+ D(UNIAPI_RELEASE_response),
+ D(UNIAPI_RELEASE_confirm),
+ D(UNIAPI_NOTIFY_request),
+ D(UNIAPI_NOTIFY_indication),
+ D(UNIAPI_STATUS_indication),
+ D(UNIAPI_STATUS_ENQUIRY_request),
+ D(UNIAPI_ADD_PARTY_request),
+ D(UNIAPI_ADD_PARTY_indication),
+ D(UNIAPI_PARTY_ALERTING_request),
+ D(UNIAPI_PARTY_ALERTING_indication),
+ D(UNIAPI_ADD_PARTY_ACK_request),
+ D(UNIAPI_ADD_PARTY_ACK_indication),
+ D(UNIAPI_ADD_PARTY_REJ_request),
+ D(UNIAPI_ADD_PARTY_REJ_indication),
+ D(UNIAPI_DROP_PARTY_request),
+ D(UNIAPI_DROP_PARTY_indication),
+ D(UNIAPI_DROP_PARTY_ACK_request),
+ D(UNIAPI_DROP_PARTY_ACK_indication),
+ D(UNIAPI_ABORT_CALL_request),
+};
+#undef D
+
+void
+uni_print_api(char *buf, size_t bufsiz, u_int type, u_int cookie,
+ const void *msg, struct unicx *cx)
+{
+ int old_dont_init = cx->dont_init;
+
+ uni_print_init(buf, bufsiz, cx);
+ cx->dont_init = 1;
+
+ if (type >= sizeof(msgs) / sizeof(msgs[0]) || msgs[type] == NULL) {
+ uni_print_flag("UNIAPI_UNKNOWN", cx);
+ uni_print_entry(cx, "sig", "%u", type);
+ uni_print_entry(cx, "cookie", "%u", cookie);
+ goto out;
+ }
+
+ uni_print_flag(msgs[type], cx);
+ uni_print_entry(cx, "cookie", "%u", cookie);
+ cx->indent++;
+
+ switch (type) {
+
+ case UNIAPI_ERROR:
+ {
+ const struct uniapi_error *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_entry(cx, "reason", "%s", uni_strerr(api->reason));
+ uni_print_entry(cx, "state", "U%u", api->state);
+ break;
+ }
+
+ case UNIAPI_CALL_CREATED:
+ {
+ const struct uniapi_call_created *api = msg;
+
+ uni_print_cref(NULL, 0, &api->cref, cx);
+ break;
+ }
+
+ case UNIAPI_CALL_DESTROYED:
+ {
+ const struct uniapi_call_destroyed *api = msg;
+
+ uni_print_cref(NULL, 0, &api->cref, cx);
+ break;
+ }
+
+ case UNIAPI_PARTY_CREATED:
+ {
+ const struct uniapi_party_created *api = msg;
+
+ uni_print_cref(NULL, 0, &api->cref, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_EPREF,
+ (const union uni_ieall *)&api->epref, cx);
+ break;
+ }
+
+ case UNIAPI_PARTY_DESTROYED:
+ {
+ const struct uniapi_party_destroyed *api = msg;
+
+ uni_print_cref(NULL, 0, &api->cref, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_EPREF,
+ (const union uni_ieall *)&api->epref, cx);
+ break;
+ }
+
+ case UNIAPI_LINK_ESTABLISH_request:
+ case UNIAPI_LINK_ESTABLISH_confirm:
+ case UNIAPI_LINK_RELEASE_request:
+ case UNIAPI_LINK_RELEASE_confirm:
+ break;
+
+ case UNIAPI_RESET_request:
+ {
+ const struct uniapi_reset_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_RESTART,
+ (const union uni_ieall *)&api->restart, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CONNID,
+ (const union uni_ieall *)&api->restart, cx);
+ break;
+ }
+
+ case UNIAPI_RESET_confirm:
+ {
+ const struct uniapi_reset_confirm *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_RESTART,
+ (const union uni_ieall *)&api->restart, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CONNID,
+ (const union uni_ieall *)&api->restart, cx);
+ break;
+ }
+
+ case UNIAPI_RESET_indication:
+ {
+ const struct uniapi_reset_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_RESTART,
+ (const union uni_ieall *)&api->restart, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CONNID,
+ (const union uni_ieall *)&api->restart, cx);
+ break;
+ }
+
+ case UNIAPI_RESET_ERROR_indication:
+ {
+ const struct uniapi_reset_error_indication *api = msg;
+ static const struct uni_print_tbl reason[] = {
+#define DEF(NAME, VALUE, STR) { STR, VALUE },
+ UNIAPI_DEF_RESET_ERRORS(DEF)
+#undef DEF
+ { NULL, 0 }
+ };
+ static const struct uni_print_tbl source[] = {
+ { "start", 0 },
+ { "respond", 1 },
+ { NULL, 0 }
+ };
+
+ uni_print_eol(cx);
+ uni_print_tbl("source", api->source, source, cx);
+ uni_print_tbl("reason", api->reason, reason, cx);
+ break;
+ }
+
+ case UNIAPI_RESET_response:
+ {
+ const struct uniapi_reset_response *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_RESTART,
+ (const union uni_ieall *)&api->restart, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CONNID,
+ (const union uni_ieall *)&api->restart, cx);
+ break;
+ }
+
+ case UNIAPI_RESET_ERROR_response:
+ {
+ const struct uniapi_reset_error_response *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CAUSE,
+ (const union uni_ieall *)&api->cause, cx);
+ break;
+ }
+
+ case UNIAPI_RESET_STATUS_indication:
+ {
+ const struct uniapi_reset_status_indication *api = msg;
+
+ uni_print_cref(NULL, 0, &api->cref, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CALLSTATE,
+ (const union uni_ieall *)&api->callstate, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CAUSE,
+ (const union uni_ieall *)&api->cause, cx);
+ break;
+ }
+
+ case UNIAPI_SETUP_request:
+ {
+ const struct uniapi_setup_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_SETUP,
+ (const union uni_msgall *)&api->setup, cx);
+ break;
+ }
+
+ case UNIAPI_SETUP_indication:
+ {
+ const struct uniapi_setup_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_SETUP,
+ (const union uni_msgall *)&api->setup, cx);
+ break;
+ }
+
+ case UNIAPI_SETUP_response:
+ {
+ const struct uniapi_setup_response *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_CONNECT,
+ (const union uni_msgall *)&api->connect, cx);
+ break;
+ }
+
+ case UNIAPI_SETUP_confirm:
+ {
+ const struct uniapi_setup_confirm *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_CONNECT,
+ (const union uni_msgall *)&api->connect, cx);
+ break;
+ }
+
+ case UNIAPI_SETUP_COMPLETE_indication:
+ {
+ const struct uniapi_setup_complete_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_CONNECT_ACK,
+ (const union uni_msgall *)&api->connect_ack, cx);
+ break;
+ }
+
+ case UNIAPI_SETUP_COMPLETE_request:
+ {
+ const struct uniapi_setup_complete_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_CONNECT_ACK,
+ (const union uni_msgall *)&api->connect_ack, cx);
+ break;
+ }
+
+ case UNIAPI_ALERTING_request:
+ {
+ const struct uniapi_alerting_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_ALERTING,
+ (const union uni_msgall *)&api->alerting, cx);
+ break;
+ }
+
+ case UNIAPI_ALERTING_indication:
+ {
+ const struct uniapi_alerting_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_ALERTING,
+ (const union uni_msgall *)&api->alerting, cx);
+ break;
+ }
+
+ case UNIAPI_PROCEEDING_request:
+ {
+ const struct uniapi_proceeding_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_CALL_PROC,
+ (const union uni_msgall *)&api->call_proc, cx);
+ break;
+ }
+
+ case UNIAPI_PROCEEDING_indication:
+ {
+ const struct uniapi_proceeding_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_CALL_PROC,
+ (const union uni_msgall *)&api->call_proc, cx);
+ break;
+ }
+
+ case UNIAPI_RELEASE_request:
+ {
+ const struct uniapi_release_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_RELEASE,
+ (const union uni_msgall *)&api->release, cx);
+ break;
+ }
+
+ case UNIAPI_RELEASE_indication:
+ {
+ const struct uniapi_release_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_RELEASE,
+ (const union uni_msgall *)&api->release, cx);
+ break;
+ }
+
+ case UNIAPI_RELEASE_response:
+ {
+ const struct uniapi_release_response *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_RELEASE_COMPL,
+ (const union uni_msgall *)&api->release_compl, cx);
+ break;
+ }
+ case UNIAPI_RELEASE_confirm:
+ {
+ const struct uniapi_release_confirm *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_RELEASE,
+ (const union uni_msgall *)&api->release, cx);
+ break;
+ }
+
+ case UNIAPI_NOTIFY_request:
+ {
+ const struct uniapi_notify_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_NOTIFY,
+ (const union uni_msgall *)&api->notify, cx);
+ break;
+ }
+
+ case UNIAPI_NOTIFY_indication:
+ {
+ const struct uniapi_notify_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_NOTIFY,
+ (const union uni_msgall *)&api->notify, cx);
+ break;
+ }
+
+ case UNIAPI_STATUS_indication:
+ {
+ const struct uniapi_status_indication *api = msg;
+
+ uni_print_cref(NULL, 0, &api->cref, cx);
+ uni_print_eol(cx);
+ uni_print_entry(cx, "my_state", "U%u", api->my_state);
+ uni_print_entry(cx, "my_cause", "%s",
+ uni_ie_cause2str(UNI_CODING_ITU, api->my_cause));
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CALLSTATE,
+ (const union uni_ieall *)&api->his_state, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CAUSE,
+ (const union uni_ieall *)&api->his_cause, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_EPREF,
+ (const union uni_ieall *)&api->epref, cx);
+ break;
+ }
+
+ case UNIAPI_STATUS_ENQUIRY_request:
+ {
+ const struct uniapi_status_enquiry_request *api = msg;
+
+ uni_print_cref(NULL, 0, &api->cref, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_EPREF,
+ (const union uni_ieall *)&api->epref, cx);
+ break;
+ }
+
+ case UNIAPI_ADD_PARTY_request:
+ {
+ const struct uniapi_add_party_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_ADD_PARTY,
+ (const union uni_msgall *)&api->add, cx);
+ break;
+ }
+
+ case UNIAPI_ADD_PARTY_indication:
+ {
+ const struct uniapi_add_party_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_ADD_PARTY,
+ (const union uni_msgall *)&api->add, cx);
+ break;
+ }
+
+ case UNIAPI_PARTY_ALERTING_request:
+ {
+ const struct uniapi_party_alerting_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_PARTY_ALERTING,
+ (const union uni_msgall *)&api->alert, cx);
+ break;
+ }
+
+ case UNIAPI_PARTY_ALERTING_indication:
+ {
+ const struct uniapi_party_alerting_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_PARTY_ALERTING,
+ (const union uni_msgall *)&api->alert, cx);
+ break;
+ }
+
+ case UNIAPI_ADD_PARTY_ACK_request:
+ {
+ const struct uniapi_add_party_ack_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_ADD_PARTY_ACK,
+ (const union uni_msgall *)&api->ack, cx);
+ break;
+ }
+
+ case UNIAPI_ADD_PARTY_ACK_indication:
+ {
+ const struct uniapi_add_party_ack_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_ADD_PARTY_ACK,
+ (const union uni_msgall *)&api->ack, cx);
+ break;
+ }
+
+ case UNIAPI_ADD_PARTY_REJ_request:
+ {
+ const struct uniapi_add_party_rej_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_ADD_PARTY_REJ,
+ (const union uni_msgall *)&api->rej, cx);
+ break;
+ }
+
+ case UNIAPI_ADD_PARTY_REJ_indication:
+ {
+ const struct uniapi_add_party_rej_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_ADD_PARTY_REJ,
+ (const union uni_msgall *)&api->rej, cx);
+ break;
+ }
+
+ case UNIAPI_DROP_PARTY_request:
+ {
+ const struct uniapi_drop_party_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_DROP_PARTY,
+ (const union uni_msgall *)&api->drop, cx);
+ break;
+ }
+
+ case UNIAPI_DROP_PARTY_indication:
+ {
+ const struct uniapi_drop_party_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_DROP_PARTY,
+ (const union uni_msgall *)&api->drop, cx);
+ break;
+ }
+
+ case UNIAPI_DROP_PARTY_ACK_request:
+ {
+ const struct uniapi_drop_party_ack_request *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_DROP_PARTY_ACK,
+ (const union uni_msgall *)&api->ack, cx);
+ break;
+ }
+
+ case UNIAPI_DROP_PARTY_ACK_indication:
+ {
+ const struct uniapi_drop_party_ack_indication *api = msg;
+
+ uni_print_eol(cx);
+ uni_print_msg(NULL, 0, UNI_DROP_PARTY,
+ (const union uni_msgall *)&api->drop, cx);
+ uni_print_eol(cx);
+ uni_print_ie(NULL, 0, UNI_IE_CRANKBACK,
+ (const union uni_ieall *)&api->crankback, cx);
+ break;
+ }
+
+ case UNIAPI_ABORT_CALL_request:
+ {
+ const struct uniapi_abort_call_request *api = msg;
+
+ uni_print_cref(NULL, 0, &api->cref, cx);
+ break;
+ }
+ }
+
+ out:
+ cx->dont_init = old_dont_init;
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_reset.c b/sys/contrib/ngatm/netnatm/sig/sig_reset.c
new file mode 100644
index 000000000000..469b9f762a6e
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/sig_reset.c
@@ -0,0 +1,827 @@
+/*
+ * Copyright (c) 1996-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/sig/sig_reset.c,v 1.11 2004/08/05 07:11:03 brandt Exp $
+ *
+ * Reset-start and reset-respond
+ */
+
+#include <netnatm/unimsg.h>
+#include <netnatm/saal/sscfudef.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/sig/uni.h>
+
+#include <netnatm/sig/unipriv.h>
+#include <netnatm/sig/unimkmsg.h>
+
+static void response_restart(struct uni *, struct uni_msg *, struct uni_all *);
+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 *,
+ 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 *,
+ uint32_t);
+
+static void start_t316(struct uni *);
+
+static void start_restart_ack(struct uni *, struct uni_msg *, struct uni_all *);
+static void start_status(struct uni *, struct uni_msg *, struct uni_all *);
+
+static int restart_forward(struct uni *, const struct uni_all *);
+
+#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME,
+static const char *const start_sigs[] = {
+ DEF_START_SIGS
+};
+#undef DEF_PRIV_SIG
+
+#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME,
+static const char *const respond_sigs[] = {
+ DEF_RESPOND_SIGS
+};
+#undef DEF_PRIV_SIG
+
+TIMER_FUNC_UNI(t317, t317_func)
+TIMER_FUNC_UNI(t316, t316_func)
+
+/*
+ * Reset-Start process.
+ */
+void
+uni_sig_start(struct uni *uni, u_int sig, uint32_t cookie,
+ struct uni_msg *m, struct uni_all *u)
+{
+ if (sig >= SIGS_END) {
+ VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to "
+ "Reset-Start", sig);
+ if (m)
+ uni_msg_destroy(m);
+ if (u)
+ UNI_FREE(u);
+ return;
+ }
+
+ VERBOSE(uni, UNI_FAC_RESTART, 1,
+ "Signal %s in state %u of Reset-Start; cookie %u",
+ start_sigs[sig], uni->glob_start, cookie);
+
+ switch (sig) {
+
+ /*
+ * User requests
+ */
+ case SIGS_RESET_request:
+ start_request(uni,
+ uni_msg_rptr(m, struct uniapi_reset_request *), cookie);
+ uni_msg_destroy(m);
+ break;
+
+ /*
+ * Timers
+ */
+ case SIGS_T316:
+ start_t316(uni);
+ break;
+
+ /*
+ * SAAL
+ */
+ case SIGS_RESTART_ACK:
+ start_restart_ack(uni, m, u);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ break;
+
+ case SIGS_STATUS:
+ start_status(uni, m, u);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ break;
+
+ case SIGS_END:
+ break;
+ }
+}
+
+/*
+ * Reset-request from USER.
+ *
+ * Q.2931:Reset-Start 1/2
+ */
+static void
+start_request(struct uni *uni, struct uniapi_reset_request *req, uint32_t cookie)
+{
+ struct uni_all *resp;
+ int err;
+
+ if (uni->glob_start != UNI_CALLSTATE_REST0) {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
+ return;
+ }
+
+ if ((resp = UNI_ALLOC()) == NULL) {
+ uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 0);
+ return;
+ }
+
+ MK_MSG_ORIG(resp, UNI_RESTART, 0, 0);
+ resp->u.restart.restart = req->restart;
+ resp->u.restart.connid = req->connid;
+
+ if (restart_forward(uni, resp))
+ return;
+
+ uni->connid_start = req->connid;
+ uni->restart_start = req->restart;
+
+ if ((err = uni_send_output(resp, uni)) != 0)
+ uniapi_uni_error(uni, UNIAPI_ERROR_ENCODING, cookie, 0);
+ UNI_FREE(resp);
+ if (err)
+ return;
+
+ uni->cnt316 = 0;
+ TIMER_START_UNI(uni, t316, uni->timer316);
+ uni->glob_start = UNI_CALLSTATE_REST1;
+
+ VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 1");
+
+
+ uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
+}
+
+/*
+ * T316 timeout function
+ */
+static void
+t316_func(struct uni *uni)
+{
+ uni_enq_start(uni, SIGS_T316, 0, NULL, NULL);
+}
+
+/*
+ * Q.2931:Reset-Start 1/2
+ */
+static void
+start_t316(struct uni *uni)
+{
+ if (uni->glob_start != UNI_CALLSTATE_REST1) {
+ VERBOSE0(uni, UNI_FAC_ERR, "T316 in state %d",
+ uni->glob_start);
+ return;
+ }
+
+ if (++uni->cnt316 == uni->init316) {
+ struct uni_msg *app;
+ struct uniapi_reset_error_indication *resp;
+
+ VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start error");
+
+ resp = ALLOC_API(struct uniapi_reset_error_indication, app);
+ if (resp != NULL) {
+ resp->source = 0;
+ resp->reason = UNIAPI_RESET_ERROR_NO_RESPONSE,
+
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_RESET_ERROR_indication, 0, app);
+ }
+
+ uni->glob_start = UNI_CALLSTATE_REST0;
+ VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 0");
+ } else {
+ struct uni_all *resp;
+
+ if ((resp = UNI_ALLOC()) == NULL)
+ return;
+
+ MK_MSG_ORIG(resp, UNI_RESTART, 0, 0);
+ resp->u.restart.restart = uni->restart_start;
+ resp->u.restart.connid = uni->connid_start;
+
+ (void)uni_send_output(resp, uni);
+
+ UNI_FREE(resp);
+
+ TIMER_START_UNI(uni, t316, uni->timer316);
+ }
+}
+
+/*
+ * Got RESTART_ACK.
+ */
+static void
+start_restart_ack(struct uni *uni, struct uni_msg *m, struct uni_all *u)
+{
+ enum uni_callstate new_state;
+ struct uniapi_reset_confirm *conf;
+ struct uni_msg *app;
+
+ if (uni->glob_start == UNI_CALLSTATE_REST0) {
+ uni_respond_status_mtype(uni, &u->u.hdr.cref, uni->glob_start,
+ UNI_CAUSE_MSG_INCOMP, UNI_RESTART_ACK);
+ return;
+ }
+
+ if (uni->glob_start != UNI_CALLSTATE_REST1) {
+ ASSERT(0, ("bad global call state in Reset-Start"));
+ return;
+ }
+
+ /*
+ * If body decoding fails, this is because IEs are wrong.
+ */
+ (void)uni_decode_body(m, u, &uni->cx);
+ MANDATE_IE(uni, u->u.restart_ack.restart, UNI_IE_RESTART);
+
+ if (IE_ISGOOD(u->u.restart_ack.restart)) {
+ /*
+ * Q.2931: 5.5.2.2
+ */
+ if (u->u.restart_ack.restart.rclass == UNI_RESTART_ALL &&
+ IE_ISGOOD(u->u.restart_ack.connid)) {
+ (void)UNI_SAVE_IERR(&uni->cx, UNI_IE_CONNID,
+ u->u.restart_ack.connid.h.act,
+ UNI_IERR_UNK);
+ } else if ((u->u.restart_ack.restart.rclass == UNI_RESTART_PATH ||
+ u->u.restart_ack.restart.rclass == UNI_RESTART_CHANNEL)) {
+ MANDATE_IE(uni, u->u.restart_ack.connid, UNI_IE_CONNID);
+ }
+ }
+ /*
+ * Compare the information elements now, because
+ * we may need the new callstate for the status message
+ * below.
+ */
+ new_state = UNI_CALLSTATE_REST1;
+
+ if (IE_ISGOOD(u->u.restart_ack.restart) &&
+ IE_ISGOOD(uni->restart_start) &&
+ u->u.restart_ack.restart.rclass == uni->restart_start.rclass &&
+ !IE_ISGOOD(u->u.restart_ack.connid) == !IE_ISGOOD(uni->connid_start) &&
+ (!IE_ISGOOD(uni->connid_start) ||
+ (u->u.restart_ack.connid.vpci == uni->connid_start.vpci &&
+ u->u.restart_ack.connid.vci == uni->connid_start.vci)))
+ new_state = UNI_CALLSTATE_REST0;
+
+ switch (uni_verify(uni, u->u.hdr.act)) {
+ case VFY_RAIM:
+ case VFY_RAI:
+ uni_respond_status_verify(uni, &u->u.hdr.cref,
+ UNI_CALLSTATE_REST1, NULL, 0);
+ case VFY_I:
+ return;
+
+ case VFY_CLR:
+ uni->glob_start = UNI_CALLSTATE_REST0;
+ VERBOSE(uni, UNI_FAC_RESTART, 1,
+ "Reset-Start state := 0");
+ return;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(uni, &u->u.hdr.cref,
+ new_state, NULL, 0);
+ case VFY_OK:
+ break;
+ }
+
+ if (new_state == UNI_CALLSTATE_REST1)
+ /*
+ * Q.2931: 5.5.1.2/2
+ */
+ return;
+
+ /*
+ * Build restart.confirm signal for application
+ */
+ if (!IE_ISGOOD(u->u.restart_ack.connid))
+ u->u.restart.connid.h.present = 0;
+
+
+ if ((conf = ALLOC_API(struct uniapi_reset_confirm, app)) == NULL)
+ return;
+ conf->restart = u->u.restart.restart;
+ conf->connid = u->u.restart.connid;
+
+ TIMER_STOP_UNI(uni, t316);
+
+ uni->funcs->uni_output(uni, uni->arg, UNIAPI_RESET_confirm, 0, app);
+
+ uni->glob_start = UNI_CALLSTATE_REST0;
+ VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 0");
+}
+
+/*
+ * Reset-Start got a STATUS message.
+ *
+ * Q.2931: Reset-Start 2/2
+ *
+ * In Q.2931 only CALLSTATE_REST1 is allowed, this seems silly and to contradict
+ * 5.6.12. So allow it in any state.
+ *
+ * The following states are considered compatible:
+ *
+ * Sender Receiver(we)
+ * ------ --------
+ * Rest0 Rest0 this is the normal state OK!
+ * Rest2 Rest0 this may be the result of no answer from the API
+ * on the remote end and the us finally timing out. ERROR!
+ * Rest2 Rest1 this is normal. OK!
+ * Rest0 Rest1 RESTART_ACK was probably lost. OK!
+ *
+ * All others are wrong.
+ */
+static void
+start_status(struct uni *uni, struct uni_msg *m, struct uni_all *u)
+{
+ (void)uni_decode_body(m, u, &uni->cx);
+ MANDATE_IE(uni, u->u.status.callstate, UNI_IE_CALLSTATE);
+ MANDATE_IE(uni, u->u.status.cause, UNI_IE_CAUSE);
+ switch (uni_verify(uni, u->u.hdr.act)) {
+ case VFY_CLR:
+ uni->glob_start = UNI_CALLSTATE_REST0;
+ VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 0");
+ return;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(uni, &u->u.hdr.cref, uni->glob_start,
+ NULL, 0);
+ case VFY_I:
+ case VFY_OK:
+ break;
+ }
+ if (!IE_ISGOOD(u->u.status.callstate)) {
+ /*
+ * As a result of the strange handling above, we must
+ * process a STATUS with an invalid or missing callstate!
+ */
+ return;
+ }
+ if ((u->u.status.callstate.state == UNI_CALLSTATE_REST0 &&
+ uni->glob_start == UNI_CALLSTATE_REST0) ||
+ (u->u.status.callstate.state == UNI_CALLSTATE_REST0 &&
+ uni->glob_start == UNI_CALLSTATE_REST1) ||
+ (u->u.status.callstate.state == UNI_CALLSTATE_REST2 &&
+ uni->glob_start == UNI_CALLSTATE_REST1)) {
+ /*
+ * Implementation dependend procedure:
+ * Inform the API
+ */
+ struct uniapi_reset_status_indication *resp;
+ struct uni_msg *app;
+
+ resp = ALLOC_API(struct uniapi_reset_status_indication, app);
+ if (resp == NULL)
+ return;
+ resp->cref = u->u.hdr.cref;
+ resp->callstate = u->u.status.callstate;
+ if (IE_ISGOOD(u->u.status.cause))
+ resp->cause = u->u.status.cause;
+
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_RESET_STATUS_indication, 0, app);
+
+ } else {
+ struct uniapi_reset_error_indication *resp;
+ struct uni_msg *app;
+
+ resp = ALLOC_API(struct uniapi_reset_error_indication, app);
+ if (resp != NULL) {
+ resp->source = 0;
+ resp->reason = UNIAPI_RESET_ERROR_PEER_INCOMP_STATE,
+
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_RESET_ERROR_indication, 0, app);
+ }
+ }
+}
+
+/************************************************************/
+/*
+ * Reset-Respond process.
+ */
+void
+uni_sig_respond(struct uni *uni, u_int sig, uint32_t cookie,
+ struct uni_msg *m, struct uni_all *u)
+{
+ if (sig >= SIGR_END) {
+ VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to "
+ "Reset-Respond", sig);
+ if (m)
+ uni_msg_destroy(m);
+ if (u)
+ UNI_FREE(u);
+ return;
+ }
+
+ VERBOSE(uni, UNI_FAC_RESTART, 1,
+ "Signal %s in state %u of Reset-Respond; cookie %u",
+ respond_sigs[sig], uni->glob_respond, cookie);
+
+ switch (sig) {
+
+ /*
+ * SAAL
+ */
+ case SIGR_RESTART:
+ response_restart(uni, m, u);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ break;
+
+ case SIGR_STATUS:
+ response_status(uni, m, u);
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ break;
+
+ /*
+ * User
+ */
+ case SIGR_RESET_ERROR_response:
+ response_error(uni,
+ uni_msg_rptr(m, struct uniapi_reset_error_response *),
+ cookie);
+ uni_msg_destroy(m);
+ break;
+
+ case SIGR_RESET_response:
+ response_response(uni,
+ uni_msg_rptr(m, struct uniapi_reset_response *), cookie);
+ uni_msg_destroy(m);
+ break;
+
+ /*
+ * Timers
+ */
+ case SIGR_T317:
+ response_t317(uni);
+ return;
+
+ case SIGR_END:
+ break;
+ }
+}
+
+/*
+ * Send a RELEASE_COMPLETE to all affected calls as per
+ * F.2.3(3)
+ */
+static int
+restart_forward(struct uni *uni, const struct uni_all *u)
+{
+ struct call *c;
+ struct uni_all *resp;
+
+ if ((resp = UNI_ALLOC()) == NULL)
+ return (-1);
+
+ TAILQ_FOREACH(c, &uni->calls, link) {
+ if (u->u.restart.restart.rclass == UNI_RESTART_ALL ||
+ (IE_ISPRESENT(c->connid) &&
+ u->u.restart.connid.vpci == c->connid.vpci &&
+ (u->u.restart.restart.rclass == UNI_RESTART_PATH ||
+ u->u.restart.connid.vci == c->connid.vci))) {
+ MK_MSG_ORIG(resp, UNI_RELEASE_COMPL, c->cref, c->mine);
+ uni_release_compl(c, resp);
+ }
+ }
+
+ UNI_FREE(resp);
+ return (0);
+}
+
+/*
+ * Respond process got a restart message.
+ * Doesn't free the messages.
+ */
+static void
+response_restart(struct uni *uni, struct uni_msg *m, struct uni_all *u)
+{
+ struct uni_msg *app;
+ struct uniapi_reset_indication *ind;
+
+ if (uni->glob_respond == UNI_CALLSTATE_REST0) {
+ /*
+ * If body decoding fails, this is because IEs are wrong.
+ */
+ (void)uni_decode_body(m, u, &uni->cx);
+ MANDATE_IE(uni, u->u.restart.restart, UNI_IE_RESTART);
+ if (IE_ISGOOD(u->u.restart.restart)) {
+ /*
+ * Q.2931: 5.5.2.2
+ */
+ if (u->u.restart.restart.rclass == UNI_RESTART_ALL &&
+ IE_ISGOOD(u->u.restart.connid)) {
+ (void)UNI_SAVE_IERR(&uni->cx, UNI_IE_CONNID,
+ u->u.restart.connid.h.act,
+ UNI_IERR_UNK);
+ } else if ((u->u.restart.restart.rclass == UNI_RESTART_PATH ||
+ u->u.restart.restart.rclass == UNI_RESTART_CHANNEL)) {
+ MANDATE_IE(uni, u->u.restart.connid, UNI_IE_CONNID);
+ }
+ }
+ switch (uni_verify(uni, u->u.hdr.act)) {
+ case VFY_RAIM:
+ case VFY_RAI:
+ uni_respond_status_verify(uni, &u->u.hdr.cref,
+ UNI_CALLSTATE_REST0, NULL, 0);
+ case VFY_CLR:
+ case VFY_I:
+ return;
+
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(uni, &u->u.hdr.cref,
+ UNI_CALLSTATE_REST2, NULL, 0);
+ case VFY_OK:
+ break;
+ }
+ if (!IE_ISGOOD(u->u.restart.connid))
+ u->u.restart.connid.h.present = 0;
+
+ /*
+ * Send a RELEASE_COMPLETE to all affected calls as per
+ * F.2.3(3)
+ */
+ if (restart_forward(uni, u))
+ return;
+
+ /*
+ * Build restart signal for application
+ */
+ if ((ind = ALLOC_API(struct uniapi_reset_indication, app)) == NULL)
+ return;
+
+ ind->restart = u->u.restart.restart;
+ ind->connid = u->u.restart.connid;
+
+ uni_enq_coord(uni, SIGO_RESET_indication, 0, app);
+
+ TIMER_START_UNI(uni, t317, uni->timer317);
+ uni->glob_respond = UNI_CALLSTATE_REST2;
+
+ VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond state := 2");
+
+
+ } else if (uni->glob_respond == UNI_CALLSTATE_REST2) {
+ /*
+ * No need to decode the message. It is unexpected in this
+ * state so return a status.
+ */
+ uni_respond_status_mtype(uni, &u->u.hdr.cref, uni->glob_respond,
+ UNI_CAUSE_MSG_INCOMP, UNI_RESTART);
+
+
+ } else
+ ASSERT(0, ("bad global call state in responder"));
+}
+
+static void
+response_t317(struct uni *uni)
+{
+ struct uniapi_reset_error_indication *resp;
+ struct uni_msg *app;
+
+ if (uni->glob_respond != UNI_CALLSTATE_REST2) {
+ VERBOSE0(uni, UNI_FAC_ERR, "T317 in state %d",
+ uni->glob_respond);
+ return;
+ }
+
+ VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond error");
+
+ if ((resp = ALLOC_API(struct uniapi_reset_error_indication, app)) != NULL) {
+ resp->source = 1;
+ resp->reason = UNIAPI_RESET_ERROR_NO_CONFIRM;
+
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_RESET_ERROR_indication, 0, app);
+ }
+
+ uni->glob_respond = UNI_CALLSTATE_REST0;
+ VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond state := 0");
+}
+
+/*
+ * Error response from USER
+ */
+static void
+response_error(struct uni *uni, struct uniapi_reset_error_response *c,
+ uint32_t cookie)
+{
+ struct uni_all *resp;
+
+ if (uni->glob_respond != UNI_CALLSTATE_REST2) {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
+ return;
+ }
+
+ if ((resp = UNI_ALLOC()) == NULL) {
+ uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 0);
+ return;
+ }
+
+ MK_MSG_ORIG(resp, UNI_STATUS, 0, 1);
+ MK_IE_CALLSTATE(resp->u.status.callstate, UNI_CALLSTATE_REST2);
+
+ if (IE_ISGOOD(c->cause))
+ resp->u.status.cause = c->cause;
+ else {
+ MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_CHANNEL_NEX);
+ if (IE_ISGOOD(uni->connid_respond))
+ ADD_CAUSE_CHANNID(resp->u.status.cause,
+ uni->connid_respond.vpci,
+ uni->connid_respond.vci);
+ }
+
+ if (uni_send_output(resp, uni) != 0) {
+ uniapi_uni_error(uni, UNIAPI_ERROR_ENCODING, cookie, 0);
+ UNI_FREE(resp);
+ return;
+ }
+
+ uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
+}
+
+/*
+ * Reset-response from user.
+ */
+static void
+response_response(struct uni *uni, struct uniapi_reset_response *arg,
+ uint32_t cookie)
+{
+ struct uni_all *resp;
+
+ if (uni->glob_respond != UNI_CALLSTATE_REST2) {
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
+ return;
+ }
+
+ if (!IE_ISGOOD(arg->restart)) {
+ uniapi_uni_error(uni, UNIAPI_ERROR_MISSING_IE, cookie, 0);
+ return;
+ }
+
+ if ((resp = UNI_ALLOC()) == NULL) {
+ uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 0);
+ return;
+ }
+
+ TIMER_STOP_UNI(uni, t317);
+
+ MK_MSG_ORIG(resp, UNI_RESTART_ACK, 0, 1);
+ resp->u.restart.restart = arg->restart;
+ if (IE_ISGOOD(arg->connid))
+ resp->u.restart.connid = arg->connid;
+
+ if (uni_send_output(resp, uni) != 0) {
+ uniapi_uni_error(uni, UNIAPI_ERROR_ENCODING, cookie, 0);
+ UNI_FREE(resp);
+ return;
+ }
+
+ UNI_FREE(resp);
+
+ uni->glob_respond = UNI_CALLSTATE_REST0;
+ VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond state := 0");
+
+ uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
+}
+
+/*
+ * Reset-Response got a STATUS message.
+ *
+ * Q.2931: Reset-Response 2/2
+ *
+ * In Q.2931 only CALLSTATE_REST2 is allowed, this seems silly and to contradict
+ * 5.6.12. So allow it in any state.
+ *
+ * The following states are considered compatible:
+ *
+ * Sender Receiver
+ * ------ --------
+ * Rest0 Rest0 this is the normal state OK!
+ * Rest0 Rest2 this may be the result of no answer from the API
+ * and the Sender finally timing out. ERROR!
+ * Rest1 Rest2 this is normal. OK!
+ * Rest1 Rest0 RESTART_ACK was probably lost. OK!
+ *
+ * All others are wrong.
+ */
+static void
+response_status(struct uni *uni, struct uni_msg *m, struct uni_all *u)
+{
+ (void)uni_decode_body(m, u, &uni->cx);
+ MANDATE_IE(uni, u->u.status.callstate, UNI_IE_CALLSTATE);
+ MANDATE_IE(uni, u->u.status.cause, UNI_IE_CAUSE);
+ switch (uni_verify(uni, u->u.hdr.act)) {
+ case VFY_CLR:
+ if (uni->proto == UNIPROTO_UNI40U) {
+ uni->glob_respond = UNI_CALLSTATE_REST0;
+ VERBOSE(uni, UNI_FAC_RESTART, 1,
+ "Reset-Respond state := 0");
+ return;
+ }
+ break;
+
+ case VFY_RAIM:
+ case VFY_RAI:
+ case VFY_RAP:
+ case VFY_RAPU:
+ uni_respond_status_verify(uni, &u->u.hdr.cref,
+ uni->glob_respond, NULL, 0);
+ case VFY_I:
+ case VFY_OK:
+ break;
+ }
+ if (!IE_ISGOOD(u->u.status.callstate)) {
+ /*
+ * As a result of the strange handling above, we must
+ * process a STATUS with an invalid or missing callstate!
+ */
+ return;
+ }
+ if ((u->u.status.callstate.state == UNI_CALLSTATE_REST0 &&
+ uni->glob_respond == UNI_CALLSTATE_REST0) ||
+ (u->u.status.callstate.state == UNI_CALLSTATE_REST1 &&
+ uni->glob_respond == UNI_CALLSTATE_REST0) ||
+ (u->u.status.callstate.state == UNI_CALLSTATE_REST1 &&
+ uni->glob_respond == UNI_CALLSTATE_REST2)) {
+ /*
+ * Implementation dependend procedure:
+ * Inform the API
+ */
+ struct uniapi_reset_status_indication *resp;
+ struct uni_msg *app;
+
+ resp = ALLOC_API(struct uniapi_reset_status_indication, app);
+ if (resp == NULL)
+ return;
+
+ resp->cref = u->u.hdr.cref;
+ resp->callstate = u->u.status.callstate;
+ if (IE_ISGOOD(u->u.status.cause))
+ resp->cause = u->u.status.cause;
+
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_RESET_STATUS_indication, 0, app);
+
+ } else {
+ struct uniapi_reset_error_indication *resp;
+ struct uni_msg *app;
+
+ resp = ALLOC_API(struct uniapi_reset_error_indication, app);
+ if (resp != NULL) {
+ resp->source = 1;
+ resp->reason = UNIAPI_RESET_ERROR_PEER_INCOMP_STATE,
+
+ uni->funcs->uni_output(uni, uni->arg,
+ UNIAPI_RESET_ERROR_indication, 0, app);
+ }
+ }
+}
+
+/*
+ * T317 timeout function
+ */
+static void
+t317_func(struct uni *uni)
+{
+ uni_enq_resp(uni, SIGR_T317, 0, NULL, NULL);
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_uni.c b/sys/contrib/ngatm/netnatm/sig/sig_uni.c
new file mode 100644
index 000000000000..e620fa7521c0
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/sig_uni.c
@@ -0,0 +1,749 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/sig_uni.c,v 1.11 2004/08/05 07:11:03 brandt Exp $
+ *
+ * Instance handling
+ */
+
+#include <netnatm/unimsg.h>
+#include <netnatm/saal/sscopdef.h>
+#include <netnatm/saal/sscfudef.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/sig/uni.h>
+#include <netnatm/sig/unisig.h>
+
+#include <netnatm/sig/unipriv.h>
+
+#ifdef UNICORE
+UNICORE
+#endif
+
+#define STR(S) [S] = #S
+static const char *custat_names[] = {
+ STR(CU_STAT0),
+ STR(CU_STAT1),
+ STR(CU_STAT2),
+ STR(CU_STAT3),
+};
+static const char *globstat_names[] = {
+ STR(UNI_CALLSTATE_REST0),
+ STR(UNI_CALLSTATE_REST1),
+ STR(UNI_CALLSTATE_REST2),
+};
+
+static const char *sig_names[] = {
+ STR(UNIAPI_ERROR),
+ STR(UNIAPI_CALL_CREATED),
+ STR(UNIAPI_CALL_DESTROYED),
+ STR(UNIAPI_PARTY_CREATED),
+ STR(UNIAPI_PARTY_DESTROYED),
+ STR(UNIAPI_LINK_ESTABLISH_request),
+ STR(UNIAPI_LINK_ESTABLISH_confirm),
+ STR(UNIAPI_LINK_RELEASE_request),
+ STR(UNIAPI_LINK_RELEASE_confirm),
+ STR(UNIAPI_RESET_request),
+ STR(UNIAPI_RESET_confirm),
+ STR(UNIAPI_RESET_indication),
+ STR(UNIAPI_RESET_ERROR_indication),
+ STR(UNIAPI_RESET_response),
+ STR(UNIAPI_RESET_ERROR_response),
+ STR(UNIAPI_RESET_STATUS_indication),
+ STR(UNIAPI_SETUP_request),
+ STR(UNIAPI_SETUP_indication),
+ STR(UNIAPI_SETUP_response),
+ STR(UNIAPI_SETUP_confirm),
+ STR(UNIAPI_SETUP_COMPLETE_indication),
+ STR(UNIAPI_SETUP_COMPLETE_request),
+ STR(UNIAPI_ALERTING_request),
+ STR(UNIAPI_ALERTING_indication),
+ STR(UNIAPI_PROCEEDING_request),
+ STR(UNIAPI_PROCEEDING_indication),
+ STR(UNIAPI_RELEASE_request),
+ STR(UNIAPI_RELEASE_indication),
+ STR(UNIAPI_RELEASE_response),
+ STR(UNIAPI_RELEASE_confirm),
+ STR(UNIAPI_NOTIFY_request),
+ STR(UNIAPI_NOTIFY_indication),
+ STR(UNIAPI_STATUS_indication),
+ STR(UNIAPI_STATUS_ENQUIRY_request),
+ STR(UNIAPI_ADD_PARTY_request),
+ STR(UNIAPI_ADD_PARTY_indication),
+ STR(UNIAPI_PARTY_ALERTING_request),
+ STR(UNIAPI_PARTY_ALERTING_indication),
+ STR(UNIAPI_ADD_PARTY_ACK_request),
+ STR(UNIAPI_ADD_PARTY_ACK_indication),
+ STR(UNIAPI_ADD_PARTY_REJ_request),
+ STR(UNIAPI_ADD_PARTY_REJ_indication),
+ STR(UNIAPI_DROP_PARTY_request),
+ STR(UNIAPI_DROP_PARTY_indication),
+ STR(UNIAPI_DROP_PARTY_ACK_request),
+ STR(UNIAPI_DROP_PARTY_ACK_indication),
+ STR(UNIAPI_ABORT_CALL_request),
+};
+
+static const char *verb_names[] = {
+# define UNI_DEBUG_DEFINE(D) [UNI_FAC_##D] = #D,
+ UNI_DEBUG_FACILITIES
+# undef UNI_DEBUG_DEFINE
+};
+
+const char *
+uni_facname(enum uni_verb fac)
+{
+ static char buf[40];
+
+ if (fac >= UNI_MAXFACILITY) {
+ sprintf(buf, "FAC%u", fac);
+ return (buf);
+ }
+ return (verb_names[fac]);
+}
+
+const char *
+uni_signame(enum uni_sig sig)
+{
+ static char buf[40];
+
+ if (sig >= UNIAPI_MAXSIG) {
+ sprintf(buf, "UNIAPI_SIG%u", sig);
+ return (buf);
+ }
+ return (sig_names[sig]);
+}
+
+struct unicx *
+uni_context(struct uni *uni)
+{
+ return (&uni->cx);
+}
+
+static void
+uni_init(struct uni *uni)
+{
+ uni->working = 0;
+ uni->cref_alloc = 12;
+ uni->custat = CU_STAT0;
+ uni->glob_start = UNI_CALLSTATE_REST0;
+ uni->glob_respond = UNI_CALLSTATE_REST0;
+}
+
+static void
+uni_stop(struct uni *uni)
+{
+ struct call *c;
+
+ while ((c = TAILQ_FIRST(&uni->calls)) != NULL) {
+ TAILQ_REMOVE(&uni->calls, c, link);
+ uni_destroy_call(c, 1);
+ }
+
+ SIGQ_CLEAR(&uni->workq);
+ SIGQ_CLEAR(&uni->delq);
+}
+
+/*
+ * INSTANCE HANDLING
+ */
+struct uni *
+uni_create(void *arg, const struct uni_funcs *funcs)
+{
+ struct uni *uni;
+
+ if ((uni = INS_ALLOC()) == NULL)
+ return (NULL);
+
+ uni_init(uni);
+
+ uni->funcs = funcs;
+ uni->arg = arg;
+ uni->proto = UNIPROTO_UNI40U;
+ uni->sb_tb = 0;
+ TAILQ_INIT(&uni->workq);
+ TAILQ_INIT(&uni->delq);
+ TIMER_INIT_UNI(uni, t309);
+ uni->timer309 = UNI_T309_DEFAULT;
+ TAILQ_INIT(&uni->calls);
+ uni_initcx(&uni->cx);
+ TIMER_INIT_UNI(uni, t317);
+ TIMER_INIT_UNI(uni, t316);
+
+ uni->timer301 = UNI_T301_DEFAULT;
+ uni->init303 = UNI_T303_CNT_DEFAULT;
+ uni->timer303 = UNI_T303_DEFAULT;
+ uni->init308 = UNI_T308_CNT_DEFAULT;
+ uni->timer308 = UNI_T308_DEFAULT;
+ uni->timer310 = UNI_T310U_DEFAULT;
+ uni->timer313 = UNI_T313_DEFAULT;
+ uni->init316 = UNI_T316_CNT_DEFAULT;
+ uni->timer316 = UNI_T316_DEFAULT;
+ uni->timer317 = UNI_T317_DEFAULT;
+ uni->timer322 = UNI_T322_DEFAULT;
+ uni->init322 = UNI_T322_CNT_DEFAULT;
+ uni->timer397 = UNI_T397_DEFAULT;
+ uni->timer398 = UNI_T398_DEFAULT;
+ uni->timer399 = UNI_T399U_DEFAULT;
+
+ return (uni);
+}
+
+void
+uni_destroy(struct uni *uni)
+{
+ uni_stop(uni);
+
+ TIMER_DESTROY_UNI(uni, t309);
+ TIMER_DESTROY_UNI(uni, t316);
+ TIMER_DESTROY_UNI(uni, t317);
+
+ INS_FREE(uni);
+}
+
+void
+uni_reset(struct uni *uni)
+{
+ uni_stop(uni);
+ uni_init(uni);
+}
+
+
+/*
+ * DISPATCH SSCOP SIGNAL
+ */
+void
+uni_saal_input(struct uni *uni, enum saal_sig sig, struct uni_msg *m)
+{
+ switch (sig) {
+
+ case SAAL_ESTABLISH_indication:
+ if (m != NULL)
+ uni_msg_destroy(m);
+ uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_indication, 0, NULL);
+ break;
+
+ case SAAL_ESTABLISH_confirm:
+ if (m != NULL)
+ uni_msg_destroy(m);
+ uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_confirm, 0, NULL);
+ break;
+
+ case SAAL_RELEASE_confirm:
+ if (m != NULL)
+ uni_msg_destroy(m);
+ uni_enq_coord(uni, SIGO_SAAL_RELEASE_confirm, 0, NULL);
+ break;
+
+ case SAAL_RELEASE_indication:
+ if (m != NULL)
+ uni_msg_destroy(m);
+ uni_enq_coord(uni, SIGO_SAAL_RELEASE_indication, 0, NULL);
+ break;
+
+ case SAAL_DATA_indication:
+ uni_enq_coord(uni, SIGO_SAAL_DATA_indication, 0, m);
+ break;
+
+ case SAAL_UDATA_indication:
+ uni_enq_coord(uni, SIGO_SAAL_UDATA_indication, 0, m);
+ break;
+
+ default:
+ VERBOSE(uni, UNI_FAC_ERR, 1, "bogus saal signal %u", sig);
+ if (m != NULL)
+ uni_msg_destroy(m);
+ break;
+ }
+}
+
+static struct {
+ const char *name;
+ enum uni_sig sig;
+ size_t arglen;
+ u_int coord_sig;
+ u_int proto;
+#define UNIU 0x01
+#define UNIN 0x02
+#define PNNI 0x04
+} maptab[] = {
+ { "LINK-ESTABLISH.request", UNIAPI_LINK_ESTABLISH_request,
+ 0,
+ SIGO_LINK_ESTABLISH_request, UNIU | UNIN },
+ { "LINK-RELEASE.request", UNIAPI_LINK_RELEASE_request,
+ 0,
+ SIGO_LINK_RELEASE_request, UNIU | UNIN },
+
+ { "RESET.request", UNIAPI_RESET_request,
+ sizeof(struct uniapi_reset_request),
+ SIGO_RESET_request, UNIU | UNIN },
+ { "RESET-ERROR.response", UNIAPI_RESET_ERROR_response,
+ sizeof(struct uniapi_reset_error_response),
+ SIGO_RESET_ERROR_response, UNIU | UNIN },
+ { "RESET.response", UNIAPI_RESET_response,
+ sizeof(struct uniapi_reset_response),
+ SIGO_RESET_response, UNIU | UNIN },
+
+ { "SETUP.request", UNIAPI_SETUP_request,
+ sizeof(struct uniapi_setup_request),
+ SIGO_SETUP_request, UNIU | UNIN },
+ { "SETUP.response", UNIAPI_SETUP_response,
+ sizeof(struct uniapi_setup_response),
+ SIGO_SETUP_response, UNIU | UNIN },
+ { "SETUP-COMPLETE.request", UNIAPI_SETUP_COMPLETE_request,
+ sizeof(struct uniapi_setup_complete_request),
+ SIGO_SETUP_COMPLETE_request, UNIN },
+ { "PROCEEDING.request", UNIAPI_PROCEEDING_request,
+ sizeof(struct uniapi_proceeding_request),
+ SIGO_PROCEEDING_request, UNIU | UNIN },
+ { "ALERTING.request", UNIAPI_ALERTING_request,
+ sizeof(struct uniapi_alerting_request),
+ SIGO_ALERTING_request, UNIU | UNIN },
+ { "RELEASE.request", UNIAPI_RELEASE_request,
+ sizeof(struct uniapi_release_request),
+ SIGO_RELEASE_request, UNIU | UNIN },
+ { "RELEASE.response", UNIAPI_RELEASE_response,
+ sizeof(struct uniapi_release_response),
+ SIGO_RELEASE_response, UNIU | UNIN },
+ { "NOTIFY.request", UNIAPI_NOTIFY_request,
+ sizeof(struct uniapi_notify_request),
+ SIGO_NOTIFY_request, UNIU | UNIN },
+ { "STATUS-ENQUIRY.request", UNIAPI_STATUS_ENQUIRY_request,
+ sizeof(struct uniapi_status_enquiry_request),
+ SIGO_STATUS_ENQUIRY_request, UNIU | UNIN },
+
+ { "ADD-PARTY.request", UNIAPI_ADD_PARTY_request,
+ sizeof(struct uniapi_add_party_request),
+ SIGO_ADD_PARTY_request, UNIU | UNIN },
+ { "ADD-PARTY-ACK.request", UNIAPI_ADD_PARTY_ACK_request,
+ sizeof(struct uniapi_add_party_ack_request),
+ SIGO_ADD_PARTY_ACK_request, UNIU | UNIN },
+ { "ADD-PARTY-REJ.request", UNIAPI_ADD_PARTY_REJ_request,
+ sizeof(struct uniapi_add_party_rej_request),
+ SIGO_ADD_PARTY_REJ_request, UNIU | UNIN },
+ { "PARTY-ALERTING.request", UNIAPI_PARTY_ALERTING_request,
+ sizeof(struct uniapi_party_alerting_request),
+ SIGO_PARTY_ALERTING_request, UNIU | UNIN },
+ { "DROP-PARTY.request", UNIAPI_DROP_PARTY_request,
+ sizeof(struct uniapi_drop_party_request),
+ SIGO_DROP_PARTY_request, UNIU | UNIN },
+ { "DROP-PARTY-ACK.request", UNIAPI_DROP_PARTY_ACK_request,
+ sizeof(struct uniapi_drop_party_ack_request),
+ SIGO_DROP_PARTY_ACK_request, UNIU | UNIN },
+
+ { "ABORT-CALL.request", UNIAPI_ABORT_CALL_request,
+ sizeof(struct uniapi_abort_call_request),
+ SIGO_ABORT_CALL_request, UNIU | UNIN },
+
+ { NULL, 0, 0, 0, 0 }
+};
+
+void
+uni_uni_input(struct uni *uni, enum uni_sig sig, uint32_t cookie,
+ struct uni_msg *m)
+{
+ u_int i;
+
+ for (i = 0; maptab[i].name != NULL; i++) {
+ if (maptab[i].sig == sig) {
+ if (uni->proto == UNIPROTO_UNI40U) {
+ if (!(maptab[i].proto & UNIU))
+ uniapi_uni_error(uni,
+ UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
+ } else if(uni->proto == UNIPROTO_UNI40N) {
+ if (!(maptab[i].proto & UNIN))
+ uniapi_uni_error(uni,
+ UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
+ } else if(uni->proto == UNIPROTO_PNNI10) {
+ if (!(maptab[i].proto & PNNI))
+ uniapi_uni_error(uni,
+ UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
+ } else {
+ uniapi_uni_error(uni,
+ UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
+ }
+ if (uni_msg_len(m) != maptab[i].arglen) {
+ VERBOSE(uni, UNI_FAC_ERR, 1, "bogus data in %s"
+ " (expecting %zu, got %zu)", maptab[i].name,
+ maptab[i].arglen, uni_msg_len(m));
+ uni_msg_destroy(m);
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_ARG,
+ cookie, 0);
+ return;
+ }
+ if (maptab[i].arglen == 0) {
+ uni_msg_destroy(m);
+ m = NULL;
+ }
+ VERBOSE(uni, UNI_FAC_API, 1, "got signal %s - "
+ "delivering to Coord", maptab[i].name);
+ uni_enq_coord(uni, maptab[i].coord_sig, cookie, m);
+ return;
+ }
+ }
+ VERBOSE(uni, UNI_FAC_ERR, 1, "bogus uni signal %u", sig);
+ uni_msg_destroy(m);
+ uniapi_uni_error(uni, UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
+}
+#undef UNIU
+#undef UNIN
+#undef PNNI
+
+/**************************************************************/
+
+void
+uni_work(struct uni *uni)
+{
+ struct sig *s;
+
+ if (uni->working)
+ return;
+ uni->working = 1;
+
+ while ((s = TAILQ_FIRST(&uni->workq)) != NULL) {
+ TAILQ_REMOVE(&uni->workq, s, link);
+ switch (s->type) {
+
+ case SIG_COORD:
+ uni_sig_coord(uni, s->sig, s->cookie, s->msg);
+ break;
+
+ case SIG_RESET_START:
+ uni_sig_start(uni, s->sig, s->cookie, s->msg, s->u);
+ break;
+
+ case SIG_RESET_RESP:
+ uni_sig_respond(uni, s->sig, s->cookie, s->msg, s->u);
+ break;
+
+ case SIG_CALL:
+ uni_sig_call(s->call, s->sig, s->cookie, s->msg, s->u);
+ break;
+
+ case SIG_PARTY:
+ uni_sig_party(s->party, s->sig, s->cookie, s->msg, s->u);
+ break;
+
+ default:
+ ASSERT(0, ("bad signal type"));
+ }
+ SIG_FREE(s);
+ }
+
+ uni->working = 0;
+}
+
+/*
+ * Enqueue a signal in the working queue
+ */
+void
+uni_enq_sig(struct uni *uni, u_int type, struct call *call,
+ struct party *party, uint32_t sig, uint32_t cookie,
+ struct uni_msg *msg, struct uni_all *u)
+{
+ struct sig *s;
+
+ if ((s = SIG_ALLOC()) != NULL) {
+ s->type = type;
+ s->sig = sig;
+ s->cookie = cookie;
+ s->msg = msg;
+ s->call = call;
+ s->party = party;
+ s->u = u;
+ TAILQ_INSERT_TAIL(&uni->workq, s, link);
+ }
+}
+
+/*
+ * Enqueue a signal in the delayed queue
+ */
+void
+uni_delenq_sig(struct uni *uni, u_int type, struct call *call,
+ struct party *party, uint32_t sig, uint32_t cookie,
+ struct uni_msg *msg, struct uni_all *u)
+{
+ struct sig *s;
+
+ if ((s = SIG_ALLOC()) != NULL) {
+ s->type = type;
+ s->sig = sig;
+ s->cookie = cookie;
+ s->msg = msg;
+ s->call = call;
+ s->party = party;
+ s->u = u;
+ TAILQ_INSERT_TAIL(&uni->delq, s, link);
+ }
+}
+
+/**************************************************************/
+
+void
+uniapi_uni_error(struct uni *uni, uint32_t reason, uint32_t cookie,
+ uint32_t state)
+{
+ struct uni_msg *resp;
+ struct uniapi_error *err;
+
+ if (cookie == 0)
+ return;
+
+ resp = uni_msg_alloc(sizeof(struct uniapi_error));
+ err = uni_msg_wptr(resp, struct uniapi_error *);
+ resp->b_wptr += sizeof(struct uniapi_error);
+
+ err->reason = reason;
+ err->state = state;
+
+ uni->funcs->uni_output(uni, uni->arg, UNIAPI_ERROR, cookie, resp);
+}
+
+void
+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, uint32_t reason, uint32_t cookie)
+{
+ uniapi_uni_error(p->call->uni, reason, cookie,
+ callstates[p->call->cstate].ext);
+}
+
+/**************************************************************/
+void
+uni_status(struct uni *uni, void *arg)
+{
+ uni->funcs->status(uni, uni->arg, arg,
+ "working: %s\n", uni->working ? "yes" : "no");
+ uni->funcs->status(uni, uni->arg, arg,
+ "work queue: %sempty\n", TAILQ_EMPTY(&uni->workq)? "" : "not ");
+ uni->funcs->status(uni, uni->arg, arg,
+ "delayed work queue: %sempty\n",
+ TAILQ_EMPTY(&uni->delq)? "" : "not ");
+ uni->funcs->status(uni, uni->arg, arg,
+ "coordinator: %s\n", custat_names[uni->custat]);
+ uni->funcs->status(uni, uni->arg, arg,
+ "reset-start: %s\n", globstat_names[uni->glob_start]);
+ uni->funcs->status(uni, uni->arg, arg,
+ "reset-respond: %s\n", globstat_names[uni->glob_respond]);
+}
+
+void
+uni_undel(struct uni *uni, int (*filter)(struct sig *, void *), void *arg)
+{
+ struct sigqueue newq;
+ struct sig *s, *s1;
+
+ if (TAILQ_EMPTY(&uni->delq))
+ return;
+
+ TAILQ_INIT(&newq);
+
+ s = TAILQ_FIRST(&uni->delq);
+ while (s != NULL) {
+ s1 = TAILQ_NEXT(s, link);
+ if ((*filter)(s, arg)) {
+ TAILQ_REMOVE(&uni->delq, s, link);
+ TAILQ_INSERT_TAIL(&uni->workq, s, link);
+ }
+ s = s1;
+ }
+}
+
+void
+uni_delsig(struct uni *uni, u_int type, struct call *c, struct party *p)
+{
+ struct sig *s, *s1;
+
+ s = TAILQ_FIRST(&uni->workq);
+ while (s != NULL) {
+ s1 = TAILQ_NEXT(s, link);
+ if ((type == SIG_CALL && s->type == SIG_CALL &&
+ s->call == c) ||
+ (type == SIG_PARTY && s->type == SIG_PARTY &&
+ s->call == c && s->party == p)) {
+ TAILQ_REMOVE(&uni->workq, s, link);
+ if (s->msg)
+ uni_msg_destroy(s->msg);
+ if (s->u)
+ UNI_FREE(s->u);
+ SIG_FREE(s);
+ }
+ s = s1;
+ }
+
+ s = TAILQ_FIRST(&uni->delq);
+ while (s != NULL) {
+ s1 = TAILQ_NEXT(s, link);
+ if ((type == SIG_CALL && s->type == SIG_CALL &&
+ s->call == c) ||
+ (type == SIG_PARTY && s->type == SIG_PARTY &&
+ s->call == c && s->party == p)) {
+ TAILQ_REMOVE(&uni->delq, s, link);
+ if (s->msg)
+ uni_msg_destroy(s->msg);
+ if (s->u)
+ UNI_FREE(s->u);
+ SIG_FREE(s); \
+ }
+ s = s1;
+ }
+}
+
+/**************************************************************/
+
+void
+uni_get_config(const struct uni *uni, struct uni_config *config)
+{
+ config->proto = uni->proto;
+
+ config->popt = 0;
+ if (uni->cx.q2932)
+ config->popt |= UNIPROTO_GFP;
+
+ config->option = 0;
+ if (uni->cx.git_hard)
+ config->option |= UNIOPT_GIT_HARD;
+ if (uni->cx.bearer_hard)
+ config->option |= UNIOPT_BEARER_HARD;
+ if (uni->cx.cause_hard)
+ config->option |= UNIOPT_CAUSE_HARD;
+ if (uni->sb_tb)
+ config->popt |= UNIPROTO_SB_TB;
+
+ config->timer301 = uni->timer301;
+ config->timer303 = uni->timer303;
+ config->init303 = uni->init303;
+ config->timer308 = uni->timer308;
+ config->init308 = uni->init308;
+ config->timer309 = uni->timer309;
+ config->timer310 = uni->timer310;
+ config->timer313 = uni->timer313;
+ config->timer316 = uni->timer316;
+ config->init316 = uni->init316;
+ config->timer317 = uni->timer317;
+ config->timer322 = uni->timer322;
+ config->init322 = uni->init322;
+ config->timer397 = uni->timer397;
+ config->timer398 = uni->timer398;
+ config->timer399 = uni->timer399;
+}
+
+void
+uni_set_config(struct uni *uni, const struct uni_config *config,
+ uint32_t *mask, uint32_t *popt_mask, uint32_t *opt_mask)
+{
+ int idle;
+
+ idle = TAILQ_EMPTY(&uni->calls) &&
+ TAILQ_EMPTY(&uni->workq) &&
+ TAILQ_EMPTY(&uni->delq);
+
+ if ((*mask & UNICFG_PROTO) && idle) {
+ switch (config->proto) {
+
+ case UNIPROTO_UNI40U:
+ case UNIPROTO_UNI40N:
+ /* case UNIPROTO_PNNI10: XXX */
+ uni->proto = config->proto;
+ *mask &= ~UNICFG_PROTO;
+ break;
+ }
+ }
+ if (*popt_mask & UNIPROTO_GFP) {
+ if (config->popt & UNIPROTO_GFP) {
+ uni->cx.q2932 = 1;
+ *popt_mask &= ~UNIPROTO_GFP;
+ } else {
+ if (!uni->cx.q2932 || idle) {
+ uni->cx.q2932 = 0;
+ *popt_mask &= ~UNIPROTO_GFP;
+ }
+ }
+ }
+ if (*popt_mask & UNIPROTO_SB_TB) {
+ uni->sb_tb = ((config->popt & UNIPROTO_SB_TB) != 0);
+ *popt_mask &= ~UNIPROTO_SB_TB;
+ }
+ if (*opt_mask & UNIOPT_GIT_HARD) {
+ uni->cx.git_hard = ((config->option & UNIOPT_GIT_HARD) != 0);
+ *opt_mask &= ~UNIOPT_GIT_HARD;
+ }
+ if (*opt_mask & UNIOPT_BEARER_HARD) {
+ uni->cx.bearer_hard = ((config->option & UNIOPT_BEARER_HARD) != 0);
+ *opt_mask &= ~UNIOPT_BEARER_HARD;
+ }
+ if (*opt_mask & UNIOPT_CAUSE_HARD) {
+ uni->cx.cause_hard = ((config->option & UNIOPT_CAUSE_HARD) != 0);
+ *opt_mask &= ~UNIOPT_CAUSE_HARD;
+ }
+
+#define SET_TIMER(NAME,name) \
+ if (*mask & UNICFG_##NAME) { \
+ uni->name = config->name; \
+ *mask &= ~UNICFG_##NAME; \
+ }
+
+ SET_TIMER(TIMER301, timer301);
+ SET_TIMER(TIMER303, timer303);
+ SET_TIMER(INIT303, init303);
+ SET_TIMER(TIMER308, timer308);
+ SET_TIMER(INIT308, init308);
+ SET_TIMER(TIMER309, timer309);
+ SET_TIMER(TIMER310, timer310);
+ SET_TIMER(TIMER313, timer313);
+ SET_TIMER(TIMER316, timer316);
+ SET_TIMER(INIT316, init316);
+ SET_TIMER(TIMER317, timer317);
+ SET_TIMER(TIMER322, timer322);
+ SET_TIMER(INIT322, init322);
+ SET_TIMER(TIMER397, timer397);
+ SET_TIMER(TIMER398, timer398);
+ SET_TIMER(TIMER399, timer399);
+
+#undef SET_TIMER
+}
+
+void
+uni_set_debug(struct uni *uni, enum uni_verb fac, u_int level)
+{
+ uni->debug[fac] = level;
+}
+
+u_int
+uni_get_debug(const struct uni *uni, enum uni_verb fac)
+{
+ return (uni->debug[fac]);
+}
+
+u_int
+uni_getcustate(const struct uni *uni)
+{
+ return (uni->custat);
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_unimsgcpy.c b/sys/contrib/ngatm/netnatm/sig/sig_unimsgcpy.c
new file mode 100644
index 000000000000..1653ba7438ec
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/sig_unimsgcpy.c
@@ -0,0 +1,594 @@
+/* This file was created automatically
+ * Source file: $Begemot: libunimsg/atm/msg/msg.def,v 1.3 2003/09/19 11:58:15 hbb Exp $
+ * $FreeBSD$
+ */
+
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/sig/unimsgcpy.h>
+
+void
+copy_msg_alerting(struct uni_alerting *src, struct uni_alerting *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->connid))
+ dst->connid = src->connid;
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ if(IE_ISGOOD(src->report))
+ dst->report = src->report;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_call_proc(struct uni_call_proc *src, struct uni_call_proc *dst)
+{
+ if(IE_ISGOOD(src->connid))
+ dst->connid = src->connid;
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_connect(struct uni_connect *src, struct uni_connect *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->aal))
+ dst->aal = src->aal;
+ if(IE_ISGOOD(src->blli))
+ dst->blli = src->blli;
+ if(IE_ISGOOD(src->connid))
+ dst->connid = src->connid;
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->conned))
+ dst->conned = src->conned;
+ if(IE_ISGOOD(src->connedsub))
+ dst->connedsub = src->connedsub;
+ if(IE_ISGOOD(src->eetd))
+ dst->eetd = src->eetd;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ if(IE_ISGOOD(src->traffic))
+ dst->traffic = src->traffic;
+ if(IE_ISGOOD(src->exqos))
+ dst->exqos = src->exqos;
+ if(IE_ISGOOD(src->facility))
+ dst->facility = src->facility;
+ if(IE_ISGOOD(src->abrsetup))
+ dst->abrsetup = src->abrsetup;
+ if(IE_ISGOOD(src->abradd))
+ dst->abradd = src->abradd;
+ if(IE_ISGOOD(src->called_soft))
+ dst->called_soft = src->called_soft;
+ if(IE_ISGOOD(src->report))
+ dst->report = src->report;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_connect_ack(struct uni_connect_ack *src, struct uni_connect_ack *dst)
+{
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_release(struct uni_release *src, struct uni_release *dst)
+{
+ u_int s, d;
+
+ for(s = d = 0; s < 2; s++)
+ if(IE_ISGOOD(src->cause[s]))
+ dst->cause[d++] = src->cause[s];
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ if(IE_ISGOOD(src->facility))
+ dst->facility = src->facility;
+ if(IE_ISGOOD(src->crankback))
+ dst->crankback = src->crankback;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_release_compl(struct uni_release_compl *src, struct uni_release_compl *dst)
+{
+ u_int s, d;
+
+ for(s = d = 0; s < 2; s++)
+ if(IE_ISGOOD(src->cause[s]))
+ dst->cause[d++] = src->cause[s];
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ if(IE_ISGOOD(src->crankback))
+ dst->crankback = src->crankback;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_setup(struct uni_setup *src, struct uni_setup *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->aal))
+ dst->aal = src->aal;
+ if(IE_ISGOOD(src->traffic))
+ dst->traffic = src->traffic;
+ if(IE_ISGOOD(src->bearer))
+ dst->bearer = src->bearer;
+ if(IE_ISGOOD(src->bhli))
+ dst->bhli = src->bhli;
+ if(IE_ISGOOD(src->blli_repeat))
+ dst->blli_repeat = src->blli_repeat;
+ for(s = d = 0; s < UNI_NUM_IE_BLLI; s++)
+ if(IE_ISGOOD(src->blli[s]))
+ dst->blli[d++] = src->blli[s];
+ if(IE_ISGOOD(src->called))
+ dst->called = src->called;
+ for(s = d = 0; s < UNI_NUM_IE_CALLEDSUB; s++)
+ if(IE_ISGOOD(src->calledsub[s]))
+ dst->calledsub[d++] = src->calledsub[s];
+ if(IE_ISGOOD(src->calling))
+ dst->calling = src->calling;
+ for(s = d = 0; s < UNI_NUM_IE_CALLINGSUB; s++)
+ if(IE_ISGOOD(src->callingsub[s]))
+ dst->callingsub[d++] = src->callingsub[s];
+ if(IE_ISGOOD(src->connid))
+ dst->connid = src->connid;
+ if(IE_ISGOOD(src->qos))
+ dst->qos = src->qos;
+ if(IE_ISGOOD(src->eetd))
+ dst->eetd = src->eetd;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->scompl))
+ dst->scompl = src->scompl;
+ for(s = d = 0; s < UNI_NUM_IE_TNS; s++)
+ if(IE_ISGOOD(src->tns[s]))
+ dst->tns[d++] = src->tns[s];
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->atraffic))
+ dst->atraffic = src->atraffic;
+ if(IE_ISGOOD(src->mintraffic))
+ dst->mintraffic = src->mintraffic;
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->lij_callid))
+ dst->lij_callid = src->lij_callid;
+ if(IE_ISGOOD(src->lij_param))
+ dst->lij_param = src->lij_param;
+ if(IE_ISGOOD(src->lij_seqno))
+ dst->lij_seqno = src->lij_seqno;
+ if(IE_ISGOOD(src->exqos))
+ dst->exqos = src->exqos;
+ if(IE_ISGOOD(src->abrsetup))
+ dst->abrsetup = src->abrsetup;
+ if(IE_ISGOOD(src->abradd))
+ dst->abradd = src->abradd;
+ if(IE_ISGOOD(src->cscope))
+ dst->cscope = src->cscope;
+ if(IE_ISGOOD(src->calling_soft))
+ dst->calling_soft = src->calling_soft;
+ if(IE_ISGOOD(src->called_soft))
+ dst->called_soft = src->called_soft;
+ if(IE_ISGOOD(src->dtl_repeat))
+ dst->dtl_repeat = src->dtl_repeat;
+ for(s = d = 0; s < UNI_NUM_IE_DTL; s++)
+ if(IE_ISGOOD(src->dtl[s]))
+ dst->dtl[d++] = src->dtl[s];
+ if(IE_ISGOOD(src->report))
+ dst->report = src->report;
+ if(IE_ISGOOD(src->mdcr))
+ dst->mdcr = src->mdcr;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_status(struct uni_status *src, struct uni_status *dst)
+{
+ if(IE_ISGOOD(src->callstate))
+ dst->callstate = src->callstate;
+ if(IE_ISGOOD(src->cause))
+ dst->cause = src->cause;
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->epstate))
+ dst->epstate = src->epstate;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_status_enq(struct uni_status_enq *src, struct uni_status_enq *dst)
+{
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_notify(struct uni_notify *src, struct uni_notify *dst)
+{
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_restart(struct uni_restart *src, struct uni_restart *dst)
+{
+ if(IE_ISGOOD(src->connid))
+ dst->connid = src->connid;
+ if(IE_ISGOOD(src->restart))
+ dst->restart = src->restart;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_restart_ack(struct uni_restart_ack *src, struct uni_restart_ack *dst)
+{
+ if(IE_ISGOOD(src->connid))
+ dst->connid = src->connid;
+ if(IE_ISGOOD(src->restart))
+ dst->restart = src->restart;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_add_party(struct uni_add_party *src, struct uni_add_party *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->aal))
+ dst->aal = src->aal;
+ if(IE_ISGOOD(src->bhli))
+ dst->bhli = src->bhli;
+ if(IE_ISGOOD(src->blli))
+ dst->blli = src->blli;
+ if(IE_ISGOOD(src->called))
+ dst->called = src->called;
+ for(s = d = 0; s < UNI_NUM_IE_CALLEDSUB; s++)
+ if(IE_ISGOOD(src->calledsub[s]))
+ dst->calledsub[d++] = src->calledsub[s];
+ if(IE_ISGOOD(src->calling))
+ dst->calling = src->calling;
+ for(s = d = 0; s < UNI_NUM_IE_CALLINGSUB; s++)
+ if(IE_ISGOOD(src->callingsub[s]))
+ dst->callingsub[d++] = src->callingsub[s];
+ if(IE_ISGOOD(src->scompl))
+ dst->scompl = src->scompl;
+ for(s = d = 0; s < UNI_NUM_IE_TNS; s++)
+ if(IE_ISGOOD(src->tns[s]))
+ dst->tns[d++] = src->tns[s];
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->eetd))
+ dst->eetd = src->eetd;
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->lij_seqno))
+ dst->lij_seqno = src->lij_seqno;
+ if(IE_ISGOOD(src->calling_soft))
+ dst->calling_soft = src->calling_soft;
+ if(IE_ISGOOD(src->called_soft))
+ dst->called_soft = src->called_soft;
+ if(IE_ISGOOD(src->dtl_repeat))
+ dst->dtl_repeat = src->dtl_repeat;
+ for(s = d = 0; s < UNI_NUM_IE_DTL; s++)
+ if(IE_ISGOOD(src->dtl[s]))
+ dst->dtl[d++] = src->dtl[s];
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_add_party_ack(struct uni_add_party_ack *src, struct uni_add_party_ack *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->aal))
+ dst->aal = src->aal;
+ if(IE_ISGOOD(src->blli))
+ dst->blli = src->blli;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->eetd))
+ dst->eetd = src->eetd;
+ if(IE_ISGOOD(src->conned))
+ dst->conned = src->conned;
+ if(IE_ISGOOD(src->connedsub))
+ dst->connedsub = src->connedsub;
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->called_soft))
+ dst->called_soft = src->called_soft;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_party_alerting(struct uni_party_alerting *src, struct uni_party_alerting *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_add_party_rej(struct uni_add_party_rej *src, struct uni_add_party_rej *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->cause))
+ dst->cause = src->cause;
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->crankback))
+ dst->crankback = src->crankback;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_drop_party(struct uni_drop_party *src, struct uni_drop_party *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->cause))
+ dst->cause = src->cause;
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_drop_party_ack(struct uni_drop_party_ack *src, struct uni_drop_party_ack *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->cause))
+ dst->cause = src->cause;
+ if(IE_ISGOOD(src->uu))
+ dst->uu = src->uu;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_leaf_setup_req(struct uni_leaf_setup_req *src, struct uni_leaf_setup_req *dst)
+{
+ u_int s, d;
+
+ for(s = d = 0; s < UNI_NUM_IE_TNS; s++)
+ if(IE_ISGOOD(src->tns[s]))
+ dst->tns[d++] = src->tns[s];
+ if(IE_ISGOOD(src->calling))
+ dst->calling = src->calling;
+ for(s = d = 0; s < UNI_NUM_IE_CALLINGSUB; s++)
+ if(IE_ISGOOD(src->callingsub[s]))
+ dst->callingsub[d++] = src->callingsub[s];
+ if(IE_ISGOOD(src->called))
+ dst->called = src->called;
+ for(s = d = 0; s < UNI_NUM_IE_CALLEDSUB; s++)
+ if(IE_ISGOOD(src->calledsub[s]))
+ dst->calledsub[d++] = src->calledsub[s];
+ if(IE_ISGOOD(src->lij_callid))
+ dst->lij_callid = src->lij_callid;
+ if(IE_ISGOOD(src->lij_seqno))
+ dst->lij_seqno = src->lij_seqno;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_leaf_setup_fail(struct uni_leaf_setup_fail *src, struct uni_leaf_setup_fail *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->cause))
+ dst->cause = src->cause;
+ if(IE_ISGOOD(src->called))
+ dst->called = src->called;
+ if(IE_ISGOOD(src->calledsub))
+ dst->calledsub = src->calledsub;
+ if(IE_ISGOOD(src->lij_seqno))
+ dst->lij_seqno = src->lij_seqno;
+ for(s = d = 0; s < UNI_NUM_IE_TNS; s++)
+ if(IE_ISGOOD(src->tns[s]))
+ dst->tns[d++] = src->tns[s];
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_cobisetup(struct uni_cobisetup *src, struct uni_cobisetup *dst)
+{
+ if(IE_ISGOOD(src->facility))
+ dst->facility = src->facility;
+ if(IE_ISGOOD(src->called))
+ dst->called = src->called;
+ if(IE_ISGOOD(src->calledsub))
+ dst->calledsub = src->calledsub;
+ if(IE_ISGOOD(src->calling))
+ dst->calling = src->calling;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_facility(struct uni_facility *src, struct uni_facility *dst)
+{
+ if(IE_ISGOOD(src->facility))
+ dst->facility = src->facility;
+ if(IE_ISGOOD(src->called))
+ dst->called = src->called;
+ if(IE_ISGOOD(src->calledsub))
+ dst->calledsub = src->calledsub;
+ if(IE_ISGOOD(src->calling))
+ dst->calling = src->calling;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_modify_req(struct uni_modify_req *src, struct uni_modify_req *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->traffic))
+ dst->traffic = src->traffic;
+ if(IE_ISGOOD(src->atraffic))
+ dst->atraffic = src->atraffic;
+ if(IE_ISGOOD(src->mintraffic))
+ dst->mintraffic = src->mintraffic;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_modify_ack(struct uni_modify_ack *src, struct uni_modify_ack *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->report))
+ dst->report = src->report;
+ if(IE_ISGOOD(src->traffic))
+ dst->traffic = src->traffic;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_modify_rej(struct uni_modify_rej *src, struct uni_modify_rej *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->cause))
+ dst->cause = src->cause;
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_conn_avail(struct uni_conn_avail *src, struct uni_conn_avail *dst)
+{
+ u_int s, d;
+
+ if(IE_ISGOOD(src->notify))
+ dst->notify = src->notify;
+ for(s = d = 0; s < UNI_NUM_IE_GIT; s++)
+ if(IE_ISGOOD(src->git[s]))
+ dst->git[d++] = src->git[s];
+ if(IE_ISGOOD(src->report))
+ dst->report = src->report;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
+
+void
+copy_msg_unknown(struct uni_unknown *src, struct uni_unknown *dst)
+{
+ if(IE_ISGOOD(src->epref))
+ dst->epref = src->epref;
+ if(IE_ISGOOD(src->unrec))
+ dst->unrec = src->unrec;
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_verify.c b/sys/contrib/ngatm/netnatm/sig/sig_verify.c
new file mode 100644
index 000000000000..ae78ed8eb50f
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/sig_verify.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/sig_verify.c,v 1.19 2004/07/08 08:22:23 brandt Exp $
+ *
+ * Message verification with explicit action indicators.
+ */
+
+#include <netnatm/unimsg.h>
+#include <netnatm/saal/sscfudef.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/sig/uni.h>
+
+#include <netnatm/sig/unipriv.h>
+#include <netnatm/sig/unimkmsg.h>
+
+void
+uni_mandate_ie(struct uni *uni, enum uni_ietype ie)
+{
+ struct uni_ierr *e;
+
+ FOREACH_ERR(e, uni)
+ if (e->ie == ie) {
+ e->man = 1;
+ return;
+ }
+ if (UNI_SAVE_IERR(&uni->cx, ie, UNI_IEACT_DEFAULT, UNI_IERR_MIS))
+ uni->cx.err[uni->cx.errcnt - 1].man = 1;
+}
+
+/*
+ * This special handling is required for ADD PARTY, PARTY ALERTING and
+ * ADD PARTY ACKNOWLEDGE by Q.2971 9.5.3.2.1.
+ * It means, that the EPREF should be handled as mandatory only if
+ * no other IEs have explicit action indicators.
+ */
+void
+uni_mandate_epref(struct uni *uni, struct uni_ie_epref *epref)
+{
+ struct uni_ierr *e;
+ int maxact;
+
+ if (!IE_ISPRESENT(*epref)) {
+ /*
+ * 9.5.3.2.1 -- missing endpoint reference
+ */
+
+ /*
+ * a) if any unrecognized or IE with error has a CLEAR
+ * action indicator, this takes precedence.
+ * b) if any unrecognized or IE with error has a
+ * discard message and report action indicator, this takes
+ * precedence.
+ * c) if any unrecognized or IE with error has a
+ * discard message action indicator, this takes
+ * precedence.
+ *
+ * In any of these cases we must remove the EPREF IE
+ * if it has CLEAR, otherwise the CLEAR would take over.
+ */
+ maxact = -1;
+ FOREACH_ERR(e, uni) {
+ if (e->ie == UNI_IE_EPREF)
+ continue;
+ if (e->act == UNI_IEACT_CLEAR)
+ maxact = UNI_IEACT_CLEAR;
+ else if (e->act == UNI_IEACT_MSG_REPORT) {
+ if (maxact == -1 && maxact != UNI_IEACT_CLEAR)
+ maxact = UNI_IEACT_MSG_REPORT;
+ } else if (e->act == UNI_IEACT_MSG_IGNORE) {
+ if (maxact == -1)
+ maxact = UNI_IEACT_MSG_IGNORE;
+ }
+ }
+
+ if (maxact != -1) {
+ /* ok, second pass to remove UNI_IE_EPREF */
+ FOREACH_ERR(e, uni)
+ if (e->ie == UNI_IE_EPREF) {
+ memmove(e, e + 1,
+ (uni->cx.errcnt - (e - uni->cx.err)
+ - 1) * sizeof(uni->cx.err[0]));
+ uni->cx.errcnt--;
+ break;
+ }
+ return;
+
+ }
+
+ /*
+ * d) if nothing of the above, the IE is mandatory
+ */
+ uni_mandate_ie(uni, UNI_IE_EPREF);
+ return;
+
+ }
+ if (IE_ISGOOD(*epref))
+ return;
+
+ /*
+ * It has an error obviously
+ * 9.5.3.2.2
+ *
+ * It turns out, that Q.2931 handling just does the right thing
+ * if we don't mandate the IE.
+ */
+ return;
+}
+
+/*
+ * Look, what to do with this message. We assume, that the message itself is
+ * recognized.
+ *
+ * This is rather complicated. We must use the information provided in the
+ * fields of the context, because IEs with length errors may not be set
+ * altogether.
+ */
+enum verify
+uni_verify(struct uni *uni, enum uni_msgact msgact)
+{
+ struct uni_ierr *e1;
+
+ if (uni->debug[UNI_FAC_VERIFY] >= 2) {
+ FOREACH_ERR(e1, uni) {
+ VERBOSE(uni, UNI_FAC_VERIFY, 2, "ie=%02x err=%u man=%d"
+ " act=%u", e1->ie, e1->err, e1->man, e1->act);
+ }
+ }
+
+ /*
+ * Look for missing mandatory IEs. The action indicator is ignored
+ * according to 5.6.7.1. If IEs are missing the action is to
+ * ignore the message and report status for all messages except
+ * RELEASE, RELEASE_COMPLETE and SETUP. Because we must differentiate
+ * this RAI from other RAIs in this case, use another return code.
+ * Note, that mandatory IEs with errors are not handled here.
+ */
+ FOREACH_ERR(e1, uni) {
+ if (e1->err == UNI_IERR_MIS) {
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MANDAT);
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAIM");
+ return (VFY_RAIM);
+ }
+ }
+
+ /*
+ * When any IE with error specifies a CLR action indicator, this
+ * takes precedence obviously. There are two cases here:
+ * unrecognized IEs and IEs with error. So we look through the
+ * error array twice and send only one STATUS. Unrecognized will
+ * take precedence.
+ *
+ * 5.7.2a)
+ */
+ FOREACH_ERR(e1, uni) {
+ if (e1->act == UNI_IEACT_CLEAR && e1->err == UNI_IERR_UNK) {
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_NIMPL);
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "CLR1");
+ return (VFY_CLR);
+ }
+ }
+
+ FOREACH_ERR(e1, uni) {
+ if (e1->act == UNI_IEACT_CLEAR &&
+ (e1->err == UNI_IERR_LEN || e1->err == UNI_IERR_BAD ||
+ e1->err == UNI_IERR_ACC)) {
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_INV);
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "CLR2");
+ return (VFY_CLR);
+ }
+ }
+
+ /*
+ * Now check, whether anybody wants to explicitly ignore the message
+ * and report status.
+ *
+ * 5.7.2a)
+ */
+ FOREACH_ERR(e1, uni) {
+ if (e1->act == UNI_IEACT_MSG_REPORT && e1->err == UNI_IERR_UNK) {
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_NIMPL);
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
+ return (VFY_RAI);
+ }
+ }
+
+ FOREACH_ERR(e1, uni) {
+ if (e1->act == UNI_IEACT_MSG_REPORT &&
+ (e1->err == UNI_IERR_LEN || e1->err == UNI_IERR_BAD ||
+ e1->err == UNI_IERR_ACC)) {
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_INV);
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
+ return (VFY_RAI);
+ }
+ }
+
+ /*
+ * Now look whether some IE wants to explicitely ignore the message
+ * without any report.
+ */
+ FOREACH_ERR(e1, uni) {
+ if (e1->act == UNI_IEACT_MSG_IGNORE) {
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "I1");
+ return (VFY_I);
+ }
+ }
+
+ /*
+ * At this point we have left only
+ * mandatory and non-mandatory IEs with error that want the IE to be
+ * ignored or ignored with report or defaulted.
+ * Because a mandatory IE with errors lead to
+ * the message beeing ignored, we make this of higher
+ * precedence, than the rest.
+ */
+ FOREACH_ERR(e1, uni) {
+ if (e1->man) {
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MANDAT);
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
+ return (VFY_RAI);
+ }
+ }
+
+ /*
+ * Now look for ignoring the IE and reporting. This takes precedence
+ * over simply ignoring it. We also collect defaulted (non-mandatory)
+ * IEs.
+ *
+ * 5.7.2d) and 5.6.8.1
+ */
+ FOREACH_ERR(e1, uni) {
+ if ((e1->act == UNI_IEACT_DEFAULT ||
+ e1->act == UNI_IEACT_REPORT)
+ && e1->err != UNI_IERR_UNK) {
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_INV);
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAP");
+ return (VFY_RAP);
+ }
+ }
+
+ FOREACH_ERR(e1, uni) {
+ if ((e1->act == UNI_IEACT_DEFAULT ||
+ e1->act == UNI_IEACT_REPORT)
+ && e1->err == UNI_IERR_UNK) {
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_NIMPL);
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAPU");
+ return (VFY_RAPU);
+ }
+ }
+
+ /*
+ * This leaves us with IEs, that want to be ignored. Among these may
+ * be mandatory IEs. If we have an mandatory IEs here in the error
+ * array, then the message wil not contain enough information and
+ * must be handled according to 5.8 as either in 5.6.7.1 (this
+ * means, that mandatory IEs cannot really be ignored) or 5.7.1.
+ */
+ FOREACH_ERR(e1, uni) {
+ if (e1->man) {
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MANDAT);
+ if (msgact == UNI_MSGACT_CLEAR) {
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "CLR3");
+ return (VFY_CLR);
+ }
+ if (msgact == UNI_MSGACT_IGNORE) {
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "I2");
+ return (VFY_I);
+ }
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
+ return (VFY_RAI);
+ }
+ }
+
+ /*
+ * Now only non-mandatory IEs are left, that want to be explicitely
+ * ignored.
+ */
+ if (uni->cx.errcnt != 0)
+ MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_IE_INV);
+
+ VERBOSE(uni, UNI_FAC_VERIFY, 1, "OK");
+ return (VFY_OK);
+}
+
+/*
+ * Collect the IE identifiers for some of the known cause codes.
+ */
+void
+uni_vfy_collect_ies(struct uni *uni)
+{
+ struct uni_ierr *e;
+
+#define STUFF_IE(IE) \
+ uni->cause.u.ie.ie[uni->cause.u.ie.len++] = (IE); \
+ if (uni->cause.u.ie.len == UNI_CAUSE_IE_N) \
+ break;
+
+ uni->cause.u.ie.len = 0;
+ if (uni->cause.cause == UNI_CAUSE_MANDAT) {
+ FOREACH_ERR(e, uni) {
+ if (e->err == UNI_IERR_MIS || e->man != 0) {
+ STUFF_IE(e->ie);
+ }
+ }
+
+ } else if (uni->cause.cause == UNI_CAUSE_IE_NIMPL) {
+ FOREACH_ERR(e, uni) {
+ if (e->err == UNI_IERR_UNK) {
+ STUFF_IE(e->ie);
+ }
+ }
+
+ } else if (uni->cause.cause == UNI_CAUSE_IE_INV) {
+ FOREACH_ERR(e, uni) {
+ if (e->err == UNI_IERR_LEN ||
+ e->err == UNI_IERR_BAD ||
+ e->err == UNI_IERR_ACC) {
+ STUFF_IE(e->ie);
+ }
+ }
+ } else
+ return;
+
+ if (uni->cause.u.ie.len != 0)
+ uni->cause.h.present |= UNI_CAUSE_IE_P;
+}
+
+
+void
+uni_respond_status_verify(struct uni *uni, struct uni_cref *cref,
+ enum uni_callstate cs, struct uni_ie_epref *epref,
+ enum uni_epstate ps)
+{
+ struct uni_all *resp;
+
+ if ((resp = UNI_ALLOC()) == NULL)
+ return;
+
+ uni_vfy_collect_ies(uni);
+
+ MK_MSG_RESP(resp, UNI_STATUS, cref);
+ MK_IE_CALLSTATE(resp->u.status.callstate, cs);
+ resp->u.status.cause = uni->cause;
+ if (epref && IE_ISGOOD(*epref)) {
+ MK_IE_EPREF(resp->u.status.epref, epref->epref, !epref->flag);
+ MK_IE_EPSTATE(resp->u.status.epstate, ps);
+ }
+
+ uni_send_output(resp, uni);
+
+ UNI_FREE(resp);
+}
+
+/*
+ * Handling of Q.2971 9.5.8.1:
+ */
+void
+uni_vfy_remove_unknown(struct uni *uni)
+{
+ struct uni_ierr *e1, *e0;
+ int flag = 0;
+
+ FOREACH_ERR(e1, uni) {
+ if (e1->err == UNI_IERR_UNK) {
+ if (e1->act == UNI_IEACT_CLEAR ||
+ e1->act == UNI_IEACT_MSG_IGNORE ||
+ e1->act == UNI_IEACT_MSG_REPORT)
+ return;
+ if (e1->act == UNI_IEACT_REPORT ||
+ e1->act == UNI_IEACT_DEFAULT)
+ flag = 1;
+ }
+ }
+ if (flag)
+ return;
+ e0 = e1 = uni->cx.err;
+ while (e1 < uni->cx.err + uni->cx.errcnt) {
+ if (e1->err != UNI_IERR_UNK) {
+ if (e0 != e1)
+ *e0 = *e1;
+ e0++;
+ }
+ e1++;
+ }
+ uni->cx.errcnt = e0 - uni->cx.err;
+}
+
+/*
+ * Handling for ADD_PARTY_REJ and DROP_PARTY_ACK with bad cause
+ */
+void
+uni_vfy_remove_cause(struct uni *uni)
+{
+ struct uni_ierr *e1, *e0;
+
+ e0 = e1 = uni->cx.err;
+ while (e1 < uni->cx.err + uni->cx.errcnt) {
+ if (e1->ie != UNI_IE_CAUSE) {
+ if (e0 != e1)
+ *e0 = *e1;
+ e0++;
+ }
+ e1++;
+ }
+ uni->cx.errcnt = e0 - uni->cx.err;
+}
diff --git a/sys/contrib/ngatm/netnatm/sig/uni.h b/sys/contrib/ngatm/netnatm/sig/uni.h
new file mode 100644
index 000000000000..5af6c445d187
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/uni.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/uni.h,v 1.5 2004/07/08 08:22:24 brandt Exp $
+ *
+ * Public UNI interface
+ */
+#ifndef _NETNATM_SIG_UNI_H_
+#define _NETNATM_SIG_UNI_H_
+
+#include <netnatm/sig/unidef.h>
+
+struct uni;
+
+/* functions to be supplied by the user */
+struct uni_funcs {
+ /* output to the upper layer */
+ void (*uni_output)(struct uni *, void *, enum uni_sig,
+ uint32_t, struct uni_msg *);
+
+ /* output to the SAAL */
+ void (*saal_output)(struct uni *, void *, enum saal_sig,
+ struct uni_msg *);
+
+ /* verbosity */
+ void (*verbose)(struct uni *, void *, enum uni_verb,
+ const char *, ...) __printflike(4, 5);
+
+ /* function to 'print' status */
+ void (*status)(struct uni *, void *, void *,
+ const char *, ...) __printflike(4, 5);
+
+#ifndef _KERNEL
+ /* start a timer */
+ void *(*start_timer)(struct uni *, void *, u_int,
+ void (*)(void *), void *);
+
+ /* stop a timer */
+ void (*stop_timer)(struct uni *, void *, void *);
+#endif
+};
+
+/* create a UNI instance */
+struct uni *uni_create(void *, const struct uni_funcs *);
+
+/* destroy a UNI instance, free all resources */
+void uni_destroy(struct uni *);
+
+/* generate a status report */
+void uni_status(struct uni *, void *);
+
+/* get current instance configuration */
+void uni_get_config(const struct uni *, struct uni_config *);
+
+/* set new instance configuration */
+void uni_set_config(struct uni *, const struct uni_config *,
+ 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, uint32_t, struct uni_msg *);
+
+/* do work on pending signals */
+void uni_work(struct uni *);
+
+/* set debuging level */
+void uni_set_debug(struct uni *, enum uni_verb, u_int level);
+u_int uni_get_debug(const struct uni *, enum uni_verb);
+
+/* reset a UNI instance */
+void uni_reset(struct uni *);
+
+/* states */
+u_int uni_getcustate(const struct uni *);
+
+/* return a reference to the coding/decoding context */
+struct unicx *uni_context(struct uni *);
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/sig/unidef.h b/sys/contrib/ngatm/netnatm/sig/unidef.h
new file mode 100644
index 000000000000..7278db8b91cb
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/unidef.h
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $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
+ */
+#define UNI_DEBUG_FACILITIES \
+ UNI_DEBUG_DEFINE(TIMEOUT) \
+ UNI_DEBUG_DEFINE(RESTART) \
+ UNI_DEBUG_DEFINE(SAAL) \
+ UNI_DEBUG_DEFINE(PARSE) \
+ UNI_DEBUG_DEFINE(CALL) \
+ UNI_DEBUG_DEFINE(WARN) \
+ UNI_DEBUG_DEFINE(COORD) \
+ UNI_DEBUG_DEFINE(API) \
+ UNI_DEBUG_DEFINE(MSG) \
+ UNI_DEBUG_DEFINE(ERR) \
+ UNI_DEBUG_DEFINE(VERIFY) \
+
+enum uni_verb {
+#define UNI_DEBUG_DEFINE(D) UNI_FAC_##D,
+ UNI_DEBUG_FACILITIES
+#undef UNI_DEBUG_DEFINE
+
+ UNI_MAXFACILITY,
+};
+
+/*
+ * Default timer values and repeat counts
+ */
+#define UNI_T301_DEFAULT 180000
+#define UNI_T303_DEFAULT 4000
+#define UNI_T303_CNT_DEFAULT 2
+#define UNI_T308_DEFAULT 30000
+#define UNI_T308_CNT_DEFAULT 2
+#define UNI_T309_DEFAULT 10000
+#define UNI_T310U_DEFAULT 30000
+#define UNI_T310N_DEFAULT 10000
+#define UNI_T313_DEFAULT 4000
+#define UNI_T316_DEFAULT 120000
+#define UNI_T316_CNT_DEFAULT 2
+#define UNI_T317_DEFAULT 90000
+#define UNI_T322_DEFAULT 4000
+#define UNI_T322_CNT_DEFAULT 2
+#define UNI_T397_DEFAULT UNI_T301_DEFAULT
+#define UNI_T398_DEFAULT 4000
+#define UNI_T399U_DEFAULT (UNI_T303_DEFAULT + UNI_T310U_DEFAULT)
+#define UNI_T399N_DEFAULT (UNI_T303_DEFAULT + UNI_T310N_DEFAULT)
+
+/*
+ * Protocol support
+ */
+enum uni_proto {
+ UNIPROTO_UNI40U, /* UNI4.0 user side */
+ UNIPROTO_UNI40N, /* UNI4.0 network side */
+ UNIPROTO_PNNI10, /* PNNI1.0 */
+};
+enum uni_popt {
+ UNIPROTO_GFP = 0x0001, /* enable GFP */
+ UNIPROTO_SB_TB = 0x0002, /* Coincident Sb-Tb/Tb */
+
+ UNIPROTO_ALLMASK = 0x0003,
+};
+
+/*
+ * Other options
+ */
+enum uni_option {
+ UNIOPT_GIT_HARD = 0x0001, /* harder check of GIT IE */
+ UNIOPT_BEARER_HARD = 0x0002, /* harder check of BEARER IE */
+ UNIOPT_CAUSE_HARD = 0x0004, /* harder check of CAUSE IE */
+
+ UNIOPT_ALLMASK = 0x0007,
+};
+
+/*
+ * UNI configuration
+ */
+struct uni_config {
+ 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,
+ UNICFG_TIMER301 = 0x00000002,
+ UNICFG_TIMER303 = 0x00000004,
+ UNICFG_INIT303 = 0x00000008,
+ UNICFG_TIMER308 = 0x00000010,
+ UNICFG_INIT308 = 0x00000020,
+ UNICFG_TIMER309 = 0x00000040,
+ UNICFG_TIMER310 = 0x00000080,
+ UNICFG_TIMER313 = 0x00000100,
+ UNICFG_TIMER316 = 0x00000200,
+ UNICFG_INIT316 = 0x00000400,
+ UNICFG_TIMER317 = 0x00000800,
+ UNICFG_TIMER322 = 0x00001000,
+ UNICFG_INIT322 = 0x00002000,
+ UNICFG_TIMER397 = 0x00004000,
+ UNICFG_TIMER398 = 0x00008000,
+ UNICFG_TIMER399 = 0x00010000,
+
+ UNICFG_ALLMASK = 0x0001ffff,
+};
+
+/*
+ * API signals
+ */
+enum uni_sig {
+ UNIAPI_ERROR = 0, /* UNI -> API */
+
+ UNIAPI_CALL_CREATED = 1, /* UNI -> API */
+ UNIAPI_CALL_DESTROYED = 2, /* UNI -> API */
+ UNIAPI_PARTY_CREATED = 3, /* UNI -> API */
+ UNIAPI_PARTY_DESTROYED = 4, /* UNI -> API */
+
+ UNIAPI_LINK_ESTABLISH_request = 5, /* API -> UNI */
+ UNIAPI_LINK_ESTABLISH_confirm = 6, /* UNI -> API */
+ UNIAPI_LINK_RELEASE_request = 7, /* API -> UNI */
+ UNIAPI_LINK_RELEASE_confirm = 8, /* UNI -> API */
+
+ UNIAPI_RESET_request = 9, /* API -> UNI */
+ UNIAPI_RESET_confirm = 10, /* UNI -> API */
+ UNIAPI_RESET_indication = 11, /* UNI -> API */
+ UNIAPI_RESET_ERROR_indication = 12, /* UNI -> API */
+ UNIAPI_RESET_response = 13, /* API -> UNI */
+ UNIAPI_RESET_ERROR_response = 14, /* API -> UNI */
+ UNIAPI_RESET_STATUS_indication = 15, /* UNI -> API */
+
+ UNIAPI_SETUP_request = 16, /* API -> UNI */
+ UNIAPI_SETUP_indication = 17, /* UNI -> API */
+ UNIAPI_SETUP_response = 18, /* API -> UNI */
+ UNIAPI_SETUP_confirm = 19, /* UNI -> API */
+ UNIAPI_SETUP_COMPLETE_indication= 20, /* U-UNI -> API */
+ UNIAPI_SETUP_COMPLETE_request = 46, /* API -> N-UNI */
+ UNIAPI_ALERTING_request = 21, /* API -> UNI */
+ UNIAPI_ALERTING_indication = 22, /* UNI -> API */
+ UNIAPI_PROCEEDING_request = 23, /* API -> UNI */
+ UNIAPI_PROCEEDING_indication = 24, /* UNI -> API */
+ UNIAPI_RELEASE_request = 25, /* API -> UNI */
+ UNIAPI_RELEASE_indication = 26, /* UNI -> API */
+ UNIAPI_RELEASE_response = 27, /* API -> UNI */
+ UNIAPI_RELEASE_confirm = 28, /* UNI -> API */
+ UNIAPI_NOTIFY_request = 29, /* API -> UNI */
+ UNIAPI_NOTIFY_indication = 30, /* UNI -> API */
+ UNIAPI_STATUS_indication = 31, /* UNI -> API */
+ UNIAPI_STATUS_ENQUIRY_request = 32, /* API -> UNI */
+
+ UNIAPI_ADD_PARTY_request = 33, /* API -> UNI */
+ UNIAPI_ADD_PARTY_indication = 34, /* UNI -> API */
+ UNIAPI_PARTY_ALERTING_request = 35, /* API -> UNI */
+ UNIAPI_PARTY_ALERTING_indication= 36, /* UNI -> API */
+ UNIAPI_ADD_PARTY_ACK_request = 37, /* API -> UNI */
+ UNIAPI_ADD_PARTY_ACK_indication = 38, /* UNI -> API */
+ UNIAPI_ADD_PARTY_REJ_request = 39, /* API -> UNI */
+ UNIAPI_ADD_PARTY_REJ_indication = 40, /* UNI -> API */
+ UNIAPI_DROP_PARTY_request = 41, /* API -> UNI */
+ UNIAPI_DROP_PARTY_indication = 42, /* UNI -> API */
+ UNIAPI_DROP_PARTY_ACK_request = 43, /* API -> UNI */
+ UNIAPI_DROP_PARTY_ACK_indication= 44, /* UNI -> API */
+
+ UNIAPI_ABORT_CALL_request = 45, /* API -> UNI */
+
+ UNIAPI_MAXSIG = 47
+};
+
+struct uniapi_error {
+ uint32_t reason;
+ uint32_t state;
+};
+/* keep this in sync with atmapi.h:enum atmerr */
+
+#define UNIAPI_DEF_ERRORS(MACRO) \
+ MACRO(OK, 0, "no error") \
+ MACRO(ERROR_BAD_SIGNAL, 1, "unknown signal") \
+ MACRO(ERROR_BADCU, 2, "signal in bad co-ordinator state") \
+ MACRO(ERROR_BAD_CALLSTATE, 3, "signal in bad call state") \
+ MACRO(ERROR_BAD_EPSTATE, 4, "signal in bad endpoint state") \
+ MACRO(ERROR_BAD_ARG, 5, "bad argument") \
+ MACRO(ERROR_BAD_CALL, 6, "unknown call reference") \
+ MACRO(ERROR_BAD_PARTY, 7, "unknown party") \
+ MACRO(ERROR_BAD_CTYPE, 8, "bad type of call for signal") \
+ MACRO(ERROR_BAD_IE, 9, "bad information element") \
+ MACRO(ERROR_EPREF_INUSE, 10, "endpoint reference already in use") \
+ MACRO(ERROR_MISSING_IE, 11, "missing information element") \
+ MACRO(ERROR_ENCODING, 12, "error during message encoding") \
+ MACRO(ERROR_NOMEM, 13, "out of memory") \
+ MACRO(ERROR_BUSY, 14, "status enquiry busy")
+
+enum {
+#define DEF(NAME, VAL, STR) UNIAPI_##NAME = VAL,
+UNIAPI_DEF_ERRORS(DEF)
+#undef DEF
+};
+
+struct uniapi_call_created {
+ struct uni_cref cref;
+};
+struct uniapi_call_destroyed {
+ struct uni_cref cref;
+};
+struct uniapi_party_created {
+ struct uni_cref cref;
+ struct uni_ie_epref epref;
+};
+struct uniapi_party_destroyed {
+ struct uni_cref cref;
+ struct uni_ie_epref epref;
+};
+struct uniapi_abort_call_request {
+ struct uni_cref cref;
+};
+
+struct uniapi_reset_request {
+ struct uni_ie_restart restart;
+ struct uni_ie_connid connid;
+};
+
+struct uniapi_reset_confirm {
+ struct uni_ie_restart restart;
+ struct uni_ie_connid connid;
+};
+
+struct uniapi_reset_indication {
+ struct uni_ie_restart restart;
+ struct uni_ie_connid connid;
+
+};
+struct uniapi_reset_error_indication {
+ uint32_t source; /* 0 - start, 1 - response */
+ uint32_t reason;
+};
+
+#define UNIAPI_DEF_RESET_ERRORS(MACRO) \
+ MACRO(UNIAPI_RESET_ERROR_NO_CONFIRM, 0, \
+ "no confirmation") \
+ MACRO(UNIAPI_RESET_ERROR_NO_RESPONSE, 1, \
+ "no response") \
+ MACRO(UNIAPI_RESET_ERROR_PEER_INCOMP_STATE, 2, \
+ "incompatible state")
+enum {
+#define DEF(NAME, VALUE, STR) NAME = VALUE,
+UNIAPI_DEF_RESET_ERRORS(DEF)
+#undef DEF
+};
+
+struct uniapi_reset_response {
+ struct uni_ie_restart restart;
+ struct uni_ie_connid connid;
+};
+
+struct uniapi_reset_error_response {
+ struct uni_ie_cause cause;
+};
+
+struct uniapi_reset_status_indication {
+ struct uni_cref cref; /* STATUS message CREF */
+ struct uni_ie_callstate callstate;
+ struct uni_ie_cause cause;
+};
+
+struct uniapi_setup_request {
+ struct uni_setup setup;
+};
+struct uniapi_setup_indication {
+ struct uni_setup setup;
+};
+struct uniapi_setup_response {
+ struct uni_connect connect;
+};
+struct uniapi_setup_confirm {
+ struct uni_connect connect;
+};
+struct uniapi_setup_complete_indication {
+ struct uni_connect_ack connect_ack;
+};
+struct uniapi_setup_complete_request {
+ struct uni_connect_ack connect_ack;
+};
+
+struct uniapi_alerting_request {
+ struct uni_alerting alerting;
+};
+
+struct uniapi_alerting_indication {
+ struct uni_alerting alerting;
+};
+
+struct uniapi_proceeding_request {
+ struct uni_call_proc call_proc;
+};
+
+struct uniapi_proceeding_indication {
+ struct uni_call_proc call_proc;
+};
+
+
+struct uniapi_release_request {
+ struct uni_release release;
+};
+struct uniapi_release_indication {
+ struct uni_release release;
+};
+struct uniapi_release_response {
+ struct uni_release_compl release_compl;
+};
+/*
+ * A release confirm can come from a RELEASE COMPLETE or a RELEASE.
+ * Because the IEs in a RELEASE COMPLETE are a subset of a RELEASE,
+ * use the RELEASE here.
+ */
+struct uniapi_release_confirm {
+ struct uni_release release;
+};
+
+struct uniapi_notify_request {
+ struct uni_notify notify;
+};
+struct uniapi_notify_indication {
+ struct uni_notify notify;
+};
+
+struct uniapi_status_indication {
+ struct uni_cref cref;
+ enum uni_callstate my_state;
+ enum uni_cause my_cause;
+ struct uni_ie_callstate his_state;
+ struct uni_ie_cause his_cause;
+ struct uni_ie_epref epref;
+ struct uni_ie_epstate epstate;
+};
+struct uniapi_status_enquiry_request {
+ struct uni_cref cref;
+ struct uni_ie_epref epref;
+};
+
+struct uniapi_add_party_request {
+ struct uni_add_party add;
+};
+struct uniapi_add_party_indication {
+ struct uni_add_party add;
+};
+
+struct uniapi_party_alerting_request {
+ struct uni_party_alerting alert;
+};
+struct uniapi_party_alerting_indication {
+ struct uni_party_alerting alert;
+};
+
+struct uniapi_add_party_ack_request {
+ struct uni_add_party_ack ack;
+};
+struct uniapi_add_party_ack_indication {
+ struct uni_add_party_ack ack;
+};
+struct uniapi_add_party_rej_request {
+ struct uni_add_party_rej rej;
+};
+struct uniapi_add_party_rej_indication {
+ struct uni_add_party_rej rej;
+};
+
+struct uniapi_drop_party_request {
+ struct uni_drop_party drop;
+};
+struct uniapi_drop_party_indication {
+ struct uni_drop_party drop;
+ struct uni_ie_cause my_cause;
+};
+
+struct uniapi_drop_party_ack_request {
+ struct uni_drop_party_ack ack;
+};
+struct uniapi_drop_party_ack_indication {
+ struct uni_drop_party drop;
+ struct uni_ie_crankback crankback;
+};
+
+union uniapi_all {
+ struct uniapi_error error;
+ struct uniapi_call_created call_created;
+ struct uniapi_call_destroyed call_destroyed;
+ struct uniapi_party_created party_created;
+ struct uniapi_party_destroyed party_destroyed;
+ struct uniapi_abort_call_request abort_call_request;
+ struct uniapi_reset_request reset_request;
+ struct uniapi_reset_confirm reset_confirm;
+ struct uniapi_reset_indication reset_indication;
+ struct uniapi_reset_error_indication reset_error_indication;
+ struct uniapi_reset_response reset_response;
+ struct uniapi_reset_error_response reset_error_response;
+ struct uniapi_reset_status_indication reset_status_indication;
+ struct uniapi_setup_request setup_request;
+ struct uniapi_setup_indication setup_indication;
+ struct uniapi_setup_response setup_response;
+ struct uniapi_setup_confirm setup_confirm;
+ struct uniapi_setup_complete_indication setup_complete_indication;
+ struct uniapi_setup_complete_request setup_complete_request;
+ struct uniapi_alerting_request alerting_request;
+ struct uniapi_alerting_indication alerting_indication;
+ struct uniapi_proceeding_request proceeding_request;
+ struct uniapi_proceeding_indication proceeding_indication;
+ struct uniapi_release_request release_request;
+ struct uniapi_release_indication release_indication;
+ struct uniapi_release_response release_response;
+ struct uniapi_release_confirm release_confirm;
+ struct uniapi_notify_request notify_request;
+ struct uniapi_notify_indication notify_indication;
+ struct uniapi_status_indication status_indication;
+ struct uniapi_status_enquiry_request status_enquiry_request;
+ struct uniapi_add_party_request add_party_request;
+ struct uniapi_add_party_indication add_party_indication;
+ struct uniapi_party_alerting_request party_alerting_request;
+ struct uniapi_party_alerting_indication party_alerting_indication;
+ struct uniapi_add_party_ack_request add_party_ack_request;
+ struct uniapi_add_party_ack_indication add_party_ack_indication;
+ struct uniapi_add_party_rej_request add_party_rej_request;
+ struct uniapi_add_party_rej_indication add_party_rej_indication;
+ struct uniapi_drop_party_request drop_party_request;
+ struct uniapi_drop_party_indication drop_party_indication;
+ struct uniapi_drop_party_ack_request drop_party_ack_request;
+ struct uniapi_drop_party_ack_indication drop_party_ack_indication;
+};
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/sig/unimkmsg.h b/sys/contrib/ngatm/netnatm/sig/unimkmsg.h
new file mode 100644
index 000000000000..80264e143b1c
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/unimkmsg.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/unimkmsg.h,v 1.4 2003/09/19 12:03:34 hbb Exp $
+ *
+ * Macros to make messages.
+ */
+
+#define MK_MSG_ORIG(MSG,TYPE,CREF,FLAG) \
+ do { \
+ (MSG)->mtype = (TYPE); \
+ (MSG)->u.hdr.cref.cref = (CREF); \
+ (MSG)->u.hdr.cref.flag = (FLAG); \
+ (MSG)->u.hdr.act = UNI_MSGACT_DEFAULT; \
+ } while(0)
+
+#define MK_MSG_RESP(MSG,TYPE,CREF) \
+ do { \
+ (MSG)->mtype = (TYPE); \
+ (MSG)->u.hdr.cref.cref = (CREF)->cref; \
+ (MSG)->u.hdr.cref.flag = !(CREF)->flag; \
+ (MSG)->u.hdr.act = UNI_MSGACT_DEFAULT; \
+ } while(0)
+
+#define MK_IE_CALLSTATE(IE,CS) \
+ do { \
+ (IE).h.present = 0; \
+ IE_SETPRESENT(IE); \
+ (IE).h.coding = UNI_CODING_ITU; \
+ (IE).h.act = UNI_IEACT_DEFAULT; \
+ (IE).state = CS; \
+ } while(0)
+
+#define MK_IE_EPREF(IE,EPREF,FLAG) \
+ do { \
+ (IE).h.present = 0; \
+ IE_SETPRESENT(IE); \
+ (IE).h.coding = UNI_CODING_ITU; \
+ (IE).h.act = UNI_IEACT_DEFAULT; \
+ (IE).epref = EPREF; \
+ (IE).flag = FLAG; \
+ } while(0)
+
+#define MK_IE_EPSTATE(IE,STATE) \
+ do { \
+ (IE).h.present = 0; \
+ IE_SETPRESENT(IE); \
+ (IE).h.coding = UNI_CODING_ITU; \
+ (IE).h.act = UNI_IEACT_DEFAULT; \
+ (IE).state = STATE; \
+ } while(0)
+
+#define MK_IE_CAUSE(IE,LOC,CAUSE) \
+ do { \
+ (IE).h.present = 0; \
+ IE_SETPRESENT(IE); \
+ (IE).h.coding = UNI_CODING_ITU; \
+ (IE).h.act = UNI_IEACT_DEFAULT; \
+ (IE).loc = LOC; \
+ (IE).cause = CAUSE; \
+ } while(0)
+
+#define ADD_CAUSE_MTYPE(IE,MTYPE) \
+ do { \
+ (IE).h.present |= UNI_CAUSE_MTYPE_P; \
+ (IE).u.mtype = MTYPE; \
+ } while(0)
+
+#define ADD_CAUSE_CHANNID(IE,VPI,VCI) \
+ do { \
+ (IE).h.present |= UNI_CAUSE_VPCI_P; \
+ (IE).u.vpci.vpci = VPI; \
+ (IE).u.vpci.vci = VCI; \
+ } while(0)
+
+#define ADD_CAUSE_TIMER(IE,TIMER) \
+ do { \
+ (IE).h.present |= UNI_CAUSE_TIMER_P; \
+ (IE).u.timer[0] = (TIMER)[0]; \
+ (IE).u.timer[1] = (TIMER)[1]; \
+ (IE).u.timer[2] = (TIMER)[2]; \
+ } while(0)
+
+/************************************************************/
+
+#define COPY_FROM_RELEASE_COMPL(U,DEST) \
+ do { \
+ u_int _i, _j; \
+ \
+ for(_i = _j = 0; _i < 2; _i++) \
+ if(IE_ISGOOD((U)->u.release_compl.cause[_i])) \
+ (DEST)->cause[_j++] = \
+ (U)->u.release_compl.cause[_i]; \
+ for(_i = _j = 0; _i < UNI_NUM_IE_GIT; _i++) \
+ if(IE_ISGOOD((U)->u.release_compl.git[_i])) \
+ (DEST)->git[_j++] = \
+ (U)->u.release_compl.git[_i]; \
+ if(IE_ISGOOD((U)->u.release_compl.uu)) \
+ (DEST)->uu = (U)->u.release_compl.uu; \
+ if(IE_ISGOOD((U)->u.release_compl.crankback)) \
+ (DEST)->crankback = (U)->u.release_compl.crankback; \
+ } while(0)
+
+#define COPY_FROM_DROP_ACK(U,DEST) \
+ do { \
+ u_int _i, _j; \
+ \
+ if(IE_ISGOOD((U)->u.drop_party_ack.epref)) \
+ (DEST)->epref = (U)->u.drop_party_ack.epref; \
+ if(IE_ISGOOD((U)->u.drop_party_ack.cause)) \
+ (DEST)->cause = (U)->u.drop_party_ack.cause; \
+ if(IE_ISGOOD((U)->u.drop_party_ack.uu)) \
+ (DEST)->uu = (U)->u.drop_party_ack.uu; \
+ for(_i = _j = 0; _i < UNI_NUM_IE_GIT; _i++) \
+ if(IE_ISGOOD((U)->u.drop_party_ack.git[_i])) \
+ (DEST)->git[_j++] = \
+ (U)->u.drop_party_ack.git[_i]; \
+ } while(0)
+
+#define COPY_FROM_ADD_REJ(U,DEST) \
+ do { \
+ u_int _i, _j; \
+ \
+ if(IE_ISGOOD((U)->u.add_party_rej.epref)) \
+ (DEST)->epref = (U)->u.add_party_rej.epref; \
+ if(IE_ISGOOD((U)->u.add_party_rej.cause)) \
+ (DEST)->cause = (U)->u.add_party_rej.cause; \
+ if(IE_ISGOOD((U)->u.add_party_rej.uu)) \
+ (DEST)->uu = (U)->u.add_party_rej.uu; \
+ for(_i = _j = 0; _i < UNI_NUM_IE_GIT; _i++) \
+ if(IE_ISGOOD((U)->u.add_party_rej.git[_i])) \
+ (DEST)->git[_j++] = \
+ (U)->u.add_party_rej.git[_i]; \
+ } while(0)
diff --git a/sys/contrib/ngatm/netnatm/sig/unimsgcpy.h b/sys/contrib/ngatm/netnatm/sig/unimsgcpy.h
new file mode 100644
index 000000000000..70e4e2eeb8b4
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/unimsgcpy.h
@@ -0,0 +1,113 @@
+/* This file was created automatically
+ * Source file: $Begemot: libunimsg/atm/msg/msg.def,v 1.3 2003/09/19 11:58:15 hbb Exp $
+ * $FreeBSD$
+ */
+
+
+void
+copy_msg_alerting(struct uni_alerting *src, struct uni_alerting *dst);
+
+
+void
+copy_msg_call_proc(struct uni_call_proc *src, struct uni_call_proc *dst);
+
+
+void
+copy_msg_connect(struct uni_connect *src, struct uni_connect *dst);
+
+
+void
+copy_msg_connect_ack(struct uni_connect_ack *src, struct uni_connect_ack *dst);
+
+
+void
+copy_msg_release(struct uni_release *src, struct uni_release *dst);
+
+
+void
+copy_msg_release_compl(struct uni_release_compl *src, struct uni_release_compl *dst);
+
+
+void
+copy_msg_setup(struct uni_setup *src, struct uni_setup *dst);
+
+
+void
+copy_msg_status(struct uni_status *src, struct uni_status *dst);
+
+
+void
+copy_msg_status_enq(struct uni_status_enq *src, struct uni_status_enq *dst);
+
+
+void
+copy_msg_notify(struct uni_notify *src, struct uni_notify *dst);
+
+
+void
+copy_msg_restart(struct uni_restart *src, struct uni_restart *dst);
+
+
+void
+copy_msg_restart_ack(struct uni_restart_ack *src, struct uni_restart_ack *dst);
+
+
+void
+copy_msg_add_party(struct uni_add_party *src, struct uni_add_party *dst);
+
+
+void
+copy_msg_add_party_ack(struct uni_add_party_ack *src, struct uni_add_party_ack *dst);
+
+
+void
+copy_msg_party_alerting(struct uni_party_alerting *src, struct uni_party_alerting *dst);
+
+
+void
+copy_msg_add_party_rej(struct uni_add_party_rej *src, struct uni_add_party_rej *dst);
+
+
+void
+copy_msg_drop_party(struct uni_drop_party *src, struct uni_drop_party *dst);
+
+
+void
+copy_msg_drop_party_ack(struct uni_drop_party_ack *src, struct uni_drop_party_ack *dst);
+
+
+void
+copy_msg_leaf_setup_req(struct uni_leaf_setup_req *src, struct uni_leaf_setup_req *dst);
+
+
+void
+copy_msg_leaf_setup_fail(struct uni_leaf_setup_fail *src, struct uni_leaf_setup_fail *dst);
+
+
+void
+copy_msg_cobisetup(struct uni_cobisetup *src, struct uni_cobisetup *dst);
+
+
+void
+copy_msg_facility(struct uni_facility *src, struct uni_facility *dst);
+
+
+void
+copy_msg_modify_req(struct uni_modify_req *src, struct uni_modify_req *dst);
+
+
+void
+copy_msg_modify_ack(struct uni_modify_ack *src, struct uni_modify_ack *dst);
+
+
+void
+copy_msg_modify_rej(struct uni_modify_rej *src, struct uni_modify_rej *dst);
+
+
+void
+copy_msg_conn_avail(struct uni_conn_avail *src, struct uni_conn_avail *dst);
+
+
+void
+copy_msg_unknown(struct uni_unknown *src, struct uni_unknown *dst);
+
diff --git a/sys/contrib/ngatm/netnatm/sig/unipriv.h b/sys/contrib/ngatm/netnatm/sig/unipriv.h
new file mode 100644
index 000000000000..35dc408b9fde
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/unipriv.h
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/unipriv.h,v 1.17 2004/07/08 08:22:25 brandt Exp $
+ *
+ * Private UNI stuff.
+ */
+#ifndef unipriv_h
+#define unipriv_h
+
+#ifdef _KERNEL
+#ifdef __FreeBSD__
+#include <netgraph/atm/uni/ng_uni_cust.h>
+#endif
+#else
+#include "unicust.h"
+#endif
+
+struct call;
+struct party;
+
+enum cu_stat {
+ CU_STAT0, /* AAL connection released */
+ CU_STAT1, /* awaiting establish */
+ CU_STAT2, /* awaiting release */
+ CU_STAT3, /* AAL connection established */
+};
+
+/*
+ * Internal Signals
+ */
+#define DEF_COORD_SIGS \
+ DEF_PRIV_SIG(O_SAAL_ESTABLISH_indication, SAAL) \
+ DEF_PRIV_SIG(O_SAAL_ESTABLISH_confirm, SAAL) \
+ DEF_PRIV_SIG(O_SAAL_RELEASE_indication, SAAL) \
+ DEF_PRIV_SIG(O_SAAL_RELEASE_confirm, SAAL) \
+ DEF_PRIV_SIG(O_SAAL_DATA_indication, SAAL) \
+ DEF_PRIV_SIG(O_SAAL_UDATA_indication, SAAL) \
+ DEF_PRIV_SIG(O_T309, Coord) \
+ DEF_PRIV_SIG(O_DATA, Coord) \
+ DEF_PRIV_SIG(O_LINK_ESTABLISH_request, API) \
+ DEF_PRIV_SIG(O_LINK_RELEASE_request, API) \
+ DEF_PRIV_SIG(O_RESET_request, API) \
+ DEF_PRIV_SIG(O_RESET_response, API) \
+ DEF_PRIV_SIG(O_RESET_ERROR_response, API) \
+ DEF_PRIV_SIG(O_SETUP_request, API) \
+ DEF_PRIV_SIG(O_SETUP_response, API) \
+ DEF_PRIV_SIG(O_SETUP_COMPLETE_request, API) \
+ DEF_PRIV_SIG(O_PROCEEDING_request, API) \
+ DEF_PRIV_SIG(O_ALERTING_request, API) \
+ DEF_PRIV_SIG(O_RELEASE_request, API) \
+ DEF_PRIV_SIG(O_RELEASE_response, API) \
+ DEF_PRIV_SIG(O_NOTIFY_request, API) \
+ DEF_PRIV_SIG(O_STATUS_ENQUIRY_request, API) \
+ DEF_PRIV_SIG(O_ADD_PARTY_request, API) \
+ DEF_PRIV_SIG(O_PARTY_ALERTING_request, API) \
+ DEF_PRIV_SIG(O_ADD_PARTY_ACK_request, API) \
+ DEF_PRIV_SIG(O_ADD_PARTY_REJ_request, API) \
+ DEF_PRIV_SIG(O_DROP_PARTY_request, API) \
+ DEF_PRIV_SIG(O_DROP_PARTY_ACK_request, API) \
+ DEF_PRIV_SIG(O_ABORT_CALL_request, API) \
+ DEF_PRIV_SIG(O_CALL_DESTROYED, CallControl) \
+ DEF_PRIV_SIG(O_RESET_indication, ResetRespond) \
+ DEF_PRIV_SIG(O_END, Coord)
+
+#define DEF_RESPOND_SIGS \
+ DEF_PRIV_SIG(R_RESTART, Coord) \
+ DEF_PRIV_SIG(R_STATUS, Coord) \
+ DEF_PRIV_SIG(R_RESET_response, Coord) \
+ DEF_PRIV_SIG(R_RESET_ERROR_response, Coord) \
+ DEF_PRIV_SIG(R_T317, ResetRespond) \
+ DEF_PRIV_SIG(R_END, ResetRespond)
+
+#define DEF_START_SIGS \
+ DEF_PRIV_SIG(S_RESTART_ACK, Coord) \
+ DEF_PRIV_SIG(S_STATUS, Coord) \
+ DEF_PRIV_SIG(S_RESET_request, Coord) \
+ DEF_PRIV_SIG(S_T316, ResetStart) \
+ DEF_PRIV_SIG(S_END, ResetStart)
+
+#define DEF_CALL_SIGS \
+ DEF_PRIV_SIG(C_LINK_ESTABLISH_confirm, Coord) \
+ DEF_PRIV_SIG(C_LINK_ESTABLISH_indication, Coord) \
+ DEF_PRIV_SIG(C_LINK_ESTABLISH_ERROR_indication,Coord) \
+ DEF_PRIV_SIG(C_LINK_RELEASE_indication, Coord) \
+ DEF_PRIV_SIG(C_SETUP_request, Coord) \
+ DEF_PRIV_SIG(C_SETUP_response, Coord) \
+ DEF_PRIV_SIG(C_SETUP_COMPLETE_request, Coord) \
+ DEF_PRIV_SIG(C_PROCEEDING_request, Coord) \
+ DEF_PRIV_SIG(C_ALERTING_request, Coord) \
+ DEF_PRIV_SIG(C_RELEASE_request, Coord) \
+ DEF_PRIV_SIG(C_RELEASE_response, Coord) \
+ DEF_PRIV_SIG(C_NOTIFY_request, Coord) \
+ DEF_PRIV_SIG(C_STATUS_ENQUIRY_request, Coord) \
+ DEF_PRIV_SIG(C_ADD_PARTY_request, Coord) \
+ DEF_PRIV_SIG(C_PARTY_ALERTING_request, Coord) \
+ DEF_PRIV_SIG(C_ADD_PARTY_ACK_request, Coord) \
+ DEF_PRIV_SIG(C_ADD_PARTY_REJ_request, Coord) \
+ DEF_PRIV_SIG(C_DROP_PARTY_request, Coord) \
+ DEF_PRIV_SIG(C_DROP_PARTY_ACK_request, Coord) \
+ DEF_PRIV_SIG(C_ABORT_CALL_request, Coord) \
+ DEF_PRIV_SIG(C_UNKNOWN, Coord) \
+ DEF_PRIV_SIG(C_SETUP, Coord) \
+ DEF_PRIV_SIG(C_CALL_PROC, Coord) \
+ DEF_PRIV_SIG(C_ALERTING, Coord) \
+ DEF_PRIV_SIG(C_CONNECT, Coord) \
+ DEF_PRIV_SIG(C_CONNECT_ACK, Coord) \
+ DEF_PRIV_SIG(C_RELEASE, Coord) \
+ DEF_PRIV_SIG(C_RELEASE_COMPL, Coord) \
+ DEF_PRIV_SIG(C_COBISETUP, Coord) \
+ DEF_PRIV_SIG(C_NOTIFY, Coord) \
+ DEF_PRIV_SIG(C_STATUS, Coord) \
+ DEF_PRIV_SIG(C_STATUS_ENQ, Coord) \
+ DEF_PRIV_SIG(C_ADD_PARTY, Coord) \
+ DEF_PRIV_SIG(C_PARTY_ALERTING, Coord) \
+ DEF_PRIV_SIG(C_ADD_PARTY_ACK, Coord) \
+ DEF_PRIV_SIG(C_ADD_PARTY_REJ, Coord) \
+ DEF_PRIV_SIG(C_DROP_PARTY, Coord) \
+ DEF_PRIV_SIG(C_DROP_PARTY_ACK, Coord) \
+ DEF_PRIV_SIG(C_CALL_DELETE, CallControl) \
+ DEF_PRIV_SIG(C_T301, CallControl) \
+ DEF_PRIV_SIG(C_T303, CallControl) \
+ DEF_PRIV_SIG(C_T308, CallControl) \
+ DEF_PRIV_SIG(C_T310, CallControl) \
+ DEF_PRIV_SIG(C_T313, CallControl) \
+ DEF_PRIV_SIG(C_T322, CallControl) \
+ DEF_PRIV_SIG(C_DROP_PARTY_indication, PartyControl) \
+ DEF_PRIV_SIG(C_SEND_DROP_PARTY, PartyControl) \
+ DEF_PRIV_SIG(C_DROP_PARTY_ACK_indication, PartyControl) \
+ DEF_PRIV_SIG(C_SEND_DROP_PARTY_ACK, PartyControl) \
+ DEF_PRIV_SIG(C_ADD_PARTY_REJ_indication, PartyControl) \
+ DEF_PRIV_SIG(C_SEND_ADD_PARTY_REJ, PartyControl) \
+ DEF_PRIV_SIG(C_SEND_STATUS_ENQ, PartyControl) \
+ DEF_PRIV_SIG(C_PARTY_DESTROYED, PartyControl) \
+ DEF_PRIV_SIG(C_END, CallControl)
+
+#define DEF_PARTY_SIGS \
+ DEF_PRIV_SIG(P_SETUP, CallControl) \
+ DEF_PRIV_SIG(P_ALERTING, CallControl) \
+ DEF_PRIV_SIG(P_CONNECT, CallControl) \
+ DEF_PRIV_SIG(P_CONNECT_ACK, CallControl) \
+ DEF_PRIV_SIG(P_RELEASE, CallControl) \
+ DEF_PRIV_SIG(P_RELEASE_COMPL, CallControl) \
+ DEF_PRIV_SIG(P_STATUS, CallControl) \
+ DEF_PRIV_SIG(P_ADD_PARTY, CallControl) \
+ DEF_PRIV_SIG(P_PARTY_ALERTING, CallControl) \
+ DEF_PRIV_SIG(P_ADD_PARTY_ACK, CallControl) \
+ DEF_PRIV_SIG(P_ADD_PARTY_REJ, CallControl) \
+ DEF_PRIV_SIG(P_DROP_PARTY, CallControl) \
+ DEF_PRIV_SIG(P_DROP_PARTY_ACK, CallControl) \
+ DEF_PRIV_SIG(P_SETUP_request, CallControl) \
+ DEF_PRIV_SIG(P_SETUP_response, CallControl) \
+ DEF_PRIV_SIG(P_SETUP_COMPL_request, CallControl) \
+ DEF_PRIV_SIG(P_ALERTING_request, CallControl) \
+ DEF_PRIV_SIG(P_RELEASE_request, CallControl) \
+ DEF_PRIV_SIG(P_RELEASE_response, CallControl) \
+ DEF_PRIV_SIG(P_RELEASE_confirm, CallControl) \
+ DEF_PRIV_SIG(P_STATUS_ENQUIRY_request, CallControl) \
+ DEF_PRIV_SIG(P_ADD_PARTY_request, CallControl) \
+ DEF_PRIV_SIG(P_PARTY_ALERTING_request, CallControl) \
+ DEF_PRIV_SIG(P_ADD_PARTY_ACK_request, CallControl) \
+ DEF_PRIV_SIG(P_ADD_PARTY_REJ_request, CallControl) \
+ DEF_PRIV_SIG(P_DROP_PARTY_request, CallControl) \
+ DEF_PRIV_SIG(P_DROP_PARTY_ACK_request, CallControl) \
+ DEF_PRIV_SIG(P_PARTY_DELETE, PartyControl) \
+ DEF_PRIV_SIG(P_T397, PartyControl) \
+ DEF_PRIV_SIG(P_T398, PartyControl) \
+ DEF_PRIV_SIG(P_T399, PartyControl) \
+ DEF_PRIV_SIG(P_END, PartyControl)
+
+
+#define DEF_PRIV_SIG(NAME, FROM) SIG##NAME,
+enum coord_sig {
+ DEF_COORD_SIGS
+};
+enum respond_sig {
+ DEF_RESPOND_SIGS
+};
+enum start_sig {
+ DEF_START_SIGS
+};
+enum call_sig {
+ DEF_CALL_SIGS
+};
+enum party_sig {
+ DEF_PARTY_SIGS
+};
+#undef DEF_PRIV_SIG
+
+/*************************************************************
+ *
+ * SIGNALS and SIGNAL QUEUES
+ */
+enum {
+ SIG_COORD,
+ SIG_RESET_START,
+ SIG_RESET_RESP,
+ SIG_CALL,
+ SIG_PARTY,
+};
+
+struct sig {
+ TAILQ_ENTRY(sig) link;
+ u_int type; /* one of the above */
+ struct call *call; /* call to send to */
+ struct party *party; /* party to send to */
+ uint32_t sig; /* the signal */
+ uint32_t cookie; /* user cookie */
+ struct uni_msg *msg; /* attached message */
+ struct uni_all *u; /* dito */
+};
+TAILQ_HEAD(sigqueue, sig);
+
+#define SIGQ_CLEAR(Q) \
+ do { \
+ struct sig *s; \
+ while(!TAILQ_EMPTY(Q)) { \
+ s = TAILQ_FIRST(Q); \
+ TAILQ_REMOVE(Q, s, link); \
+ if(s->msg) uni_msg_destroy(s->msg); \
+ if(s->u) UNI_FREE(s->u); \
+ SIG_FREE(s); \
+ } \
+ } while(0)
+
+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, uint32_t cookie,
+ struct uni_msg *, struct uni_all *);
+void uni_sig_coord(struct uni *, enum coord_sig, uint32_t cookie,
+ struct uni_msg *);
+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, uint32_t cookie,
+ struct uni_msg *, struct uni_all *);
+
+/*************************************************************
+ *
+ * CALL INSTANCES
+ */
+struct party {
+ struct call *call;
+ TAILQ_ENTRY(party) link;
+ u_int epref; /* endpoint reference */
+ u_int flags; /* flags */
+ enum uni_epstate state; /* party state */
+
+ struct uni_timer t397; /* T397 */
+ struct uni_timer t398; /* T398 */
+ struct uni_timer t399; /* T399 */
+};
+#define PARTY_MINE 0x0001 /* must be 1 */
+#define PARTY_CONNECT 0x0002 /* connect request from this party */
+
+TAILQ_HEAD(partyqueue, party);
+
+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,
+ uint32_t cookie);
+u_int uni_party_act_count(struct call *, int);
+
+enum call_type {
+ CALL_NULL, /* not known yet */
+ CALL_P2P, /* normal point-to-point call */
+ CALL_COBI, /* Q.2932.1 COBI call */
+ CALL_ROOT, /* point-to-multipoint root */
+ CALL_LEAF, /* point-to-multipoint leaf */
+};
+
+enum call_state {
+ CALLST_NULL,
+ CALLST_U1, CALLST_U3, CALLST_U4, CALLST_U6, CALLST_U7, CALLST_U8,
+ CALLST_U9, CALLST_U10, CALLST_U11, CALLST_U12,
+ CALLST_N1, CALLST_N3, CALLST_N4, CALLST_N6, CALLST_N7, CALLST_N8,
+ CALLST_N9, CALLST_N10, CALLST_N11, CALLST_N12
+};
+
+struct call {
+ TAILQ_ENTRY(call) link; /* link between calls */
+ struct uni *uni; /* backpointer to owning UNI */
+ u_int cref; /* call reference value or lij seqno */
+ u_int mine; /* if TRUE this is my call */
+ enum call_type type; /* what call is it */
+ enum call_state cstate; /* the state of the call */
+ struct uni_ie_connid connid; /* the connection ID */
+ struct uni_setup msg_setup; /* retransmission */
+ struct uni_release msg_release; /* retransmission */
+ struct uni_ie_epref stat_epref; /* retransmission */
+ struct partyqueue parties;
+ u_int se_active; /* status enquiry active */
+ u_int epref_alloc;
+
+ struct uni_timer t308; /* T303 */
+ u_int cnt308;
+
+ struct uni_timer t303; /* T303 */
+ u_int cnt303;
+
+ struct uni_timer t301; /* T301 */
+ struct uni_timer t310; /* T310 */
+ struct uni_timer t313; /* T313 */
+
+ struct uni_timer t322; /* T322 */
+ u_int cnt322;
+};
+
+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,
+ 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,
+ struct uni_ie_epref *, int);
+
+extern const struct callstates {
+ const char *name;
+ enum uni_callstate ext;
+} callstates[];
+
+/*************************************************************
+ *
+ * UNI INSTANCE
+ */
+struct uni {
+ void *arg; /* user arg */
+ const struct uni_funcs *funcs;
+
+ enum uni_proto proto; /* protocol */
+ struct unicx cx; /* decoding/coding context */
+ int sb_tb : 1; /* Sb-Tb/Tb point */
+
+ struct sigqueue workq; /* work queue */
+ struct sigqueue delq; /* delayed signal queue */
+ int working;
+
+ uint32_t cref_alloc;
+
+ enum cu_stat custat; /* coordinator state */
+ struct uni_timer t309;
+ u_int timer309;
+
+ enum uni_callstate glob_start;
+ enum uni_callstate glob_respond;
+ struct uni_timer t316;
+ struct uni_timer t317;
+ struct uni_ie_connid connid_start;
+ struct uni_ie_connid connid_respond;
+ u_int cnt316;
+ struct uni_ie_restart restart_start;
+
+ struct callqueue calls;
+
+ struct uni_ie_cause cause; /* working area for verify */
+
+ /* tuneable parameters */
+ u_int timer301;
+ u_int init303;
+ u_int timer303;
+ u_int init308;
+ u_int timer308;
+ u_int timer310;
+ u_int timer313;
+ u_int init316;
+ u_int timer316;
+ u_int timer317;
+ u_int timer322;
+ u_int init322;
+ u_int timer397;
+ u_int timer398;
+ u_int timer399;
+
+ u_int debug[UNI_MAXFACILITY];
+};
+
+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);
+
+/*************************************************************
+ *
+ * INLINE FUNCTIONS
+ */
+
+/* Enqueue a signal in the working queue */
+void uni_enq_sig(struct uni *, u_int, struct call *, struct party *,
+ uint32_t, uint32_t, struct uni_msg *, struct uni_all *);
+
+/* Enqueue a signal in the delayed queue */
+void uni_delenq_sig(struct uni *, u_int, struct call *, struct party *,
+ uint32_t, uint32_t, struct uni_msg *, struct uni_all *);
+
+/* Enqueue a signal to the coordinator */
+#define uni_enq_coord(UNI, SIG, COOKIE, MSG) do { \
+ uni_enq_sig((UNI), SIG_COORD, NULL, NULL, \
+ (SIG), (COOKIE), (MSG), NULL); \
+ } while (0)
+
+/* Enqueue a delayed signal to the coordinator */
+#define uni_delenq_coord(UNI, SIG, COOKIE, MSG) do { \
+ uni_delenq_sig((UNI), SIG_COORD, NULL, NULL, \
+ (SIG), (COOKIE), (MSG), NULL); \
+ } while (0)
+
+/* Enqueue a signal to a call */
+#define uni_enq_call(CALL, SIG, COOKIE, MSG, U) do { \
+ uni_enq_sig((CALL)->uni, SIG_CALL, (CALL), NULL, \
+ (SIG), (COOKIE), (MSG), (U)); \
+ } while (0)
+
+/* Enqueue a signal to a party */
+#define uni_enq_party(PARTY, SIG, COOKIE, MSG, U) do { \
+ uni_enq_sig((PARTY)->call->uni, SIG_PARTY, (PARTY)->call, \
+ (PARTY), (SIG), (COOKIE), (MSG), (U)); \
+ } while (0)
+
+/* Enqueue a signal to RESET-START */
+#define uni_enq_start(UNI, SIG, COOKIE, MSG, U) do { \
+ uni_enq_sig((UNI), SIG_RESET_START, NULL, NULL, \
+ (SIG), (COOKIE), (MSG), (U)); \
+ } while (0)
+
+/* Enqueue a signal to RESET-RESPOND */
+#define uni_enq_resp(UNI, SIG, COOKIE, MSG, U) do { \
+ uni_enq_sig((UNI), SIG_RESET_RESP, NULL, NULL, \
+ (SIG), (COOKIE), (MSG), (U)); \
+ } while (0)
+
+int uni_send_output(struct uni_all *u, struct uni *uni);
+void uni_undel(struct uni *, int (*)(struct sig *, void *), void *);
+void uni_delsig(struct uni *, u_int, struct call *, struct party *);
+
+void uni_release_compl(struct call *, struct uni_all *);
+
+/*************************************************************/
+/*
+ * Message verification.
+ */
+#define MANDATE_IE(UNI,MSG,IE) \
+ do { \
+ if (!IE_ISGOOD(MSG)) \
+ uni_mandate_ie(UNI, IE); \
+ } while(0)
+
+enum verify {
+ VFY_OK, /* ok */
+ VFY_RAP, /* report and proceed */
+ VFY_RAPU, /* report and proceed becuase of unknown IEs */
+ VFY_I, /* ignore */
+ VFY_CLR, /* clear call */
+ VFY_RAI, /* report and ignore */
+ VFY_RAIM, /* report and ignore because if mandat. IE miss */
+};
+
+void uni_mandate_ie(struct uni *, enum uni_ietype);
+void uni_mandate_epref(struct uni *, struct uni_ie_epref *);
+enum verify uni_verify(struct uni *, enum uni_msgact);
+void uni_respond_status_verify(struct uni *, struct uni_cref *,
+ enum uni_callstate, struct uni_ie_epref *, enum uni_epstate);
+void uni_vfy_remove_unknown(struct uni *);
+void uni_vfy_remove_cause(struct uni *);
+void uni_vfy_collect_ies(struct uni *);
+
+
+void uni_respond_status(struct uni *uni, struct uni_cref *cref,
+ enum uni_callstate cs, enum uni_cause c1);
+void uni_respond_status_mtype(struct uni *uni, struct uni_cref *cref,
+ enum uni_callstate cs, enum uni_cause c1, u_int mtype);
+
+#define FOREACH_ERR(E, UNI) \
+ for ((E) = (UNI)->cx.err; (E) < (UNI)->cx.err + (UNI)->cx.errcnt; (E)++)
+
+#define ALLOC_API(TYPE,API) \
+ ({ \
+ TYPE *_tmp = NULL; \
+ \
+ if(((API) = uni_msg_alloc(sizeof(TYPE))) != NULL) { \
+ _tmp = uni_msg_wptr((API), TYPE *); \
+ (API)->b_wptr += sizeof(TYPE); \
+ memset(_tmp, 0, sizeof(TYPE)); \
+ } \
+ _tmp; \
+ })
+
+#if defined(__GNUC__) && __GNUC__ < 3
+
+#define VERBOSE(UNI, FAC, LEVEL, ARGS...) do { \
+ if ((UNI)->debug[(FAC)] >= (LEVEL)) { \
+ (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC) ,\
+ ## ARGS); \
+ } \
+ } while(0)
+
+#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)
+
+#define TIMER_DESTROY_UNI(U,T) _TIMER_DESTROY(U, (U)->T)
+#define TIMER_DESTROY_CALL(C,T) _TIMER_DESTROY((C)->uni, (C)->T)
+#define TIMER_DESTROY_PARTY(P,T) _TIMER_DESTROY((P)->call->uni, (P)->T)
+
+#define TIMER_STOP_UNI(U,T) _TIMER_STOP(U, (U)->T)
+#define TIMER_STOP_CALL(C,T) _TIMER_STOP((C)->uni, (C)->T)
+#define TIMER_STOP_PARTY(P,T) _TIMER_STOP((P)->call->uni, (P)->T)
+
+#define TIMER_START_UNI(U,T,N) _TIMER_START(U, U, (U)->T, N, _##T##_func)
+#define TIMER_START_CALL(C,T,N) _TIMER_START(C->uni, C, (C)->T, N, _##T##_func)
+#define TIMER_START_PARTY(P,T,N) _TIMER_START(P->call->uni, P, (P)->T, N, _##T##_func)
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/sig/unisig.h b/sys/contrib/ngatm/netnatm/sig/unisig.h
new file mode 100644
index 000000000000..22ff671d2922
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/unisig.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/unisig.h,v 1.4 2004/07/08 08:22:26 brandt Exp $
+ *
+ * Utility functions for signalling stuff
+ */
+#ifndef _NETNATM_SIG_UNISIG_H_
+#define _NETNATM_SIG_UNISIG_H_
+
+#include <netnatm/sig/unidef.h>
+
+/* names */
+const char *uni_signame(enum uni_sig);
+const char *uni_facname(enum uni_verb);
+
+/* return a string for the error code */
+const char *uni_strerr(u_int _err);
+
+/* format an API message */
+void uni_print_api(char *_buf, size_t _bufsiz, u_int _type, u_int _cookie,
+ const void *_msg, struct unicx *_cx);
+
+#endif
diff --git a/sys/contrib/ngatm/netnatm/unimsg.h b/sys/contrib/ngatm/netnatm/unimsg.h
new file mode 100644
index 000000000000..efc91c57a81f
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/unimsg.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1996-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/unimsg.h,v 1.4 2004/07/08 08:21:46 brandt Exp $
+ *
+ * This defines the structure of messages as handled by this library.
+ */
+#ifndef _NETNATM_UNIMSG_H_
+#define _NETNATM_UNIMSG_H_
+
+#include <sys/types.h>
+#ifdef _KERNEL
+#ifdef __FreeBSD__
+#include <sys/systm.h>
+#endif
+#include <sys/stdint.h>
+#else
+#include <string.h>
+#include <stdint.h>
+#endif
+
+struct uni_msg {
+ u_char *b_wptr; /* tail pointer */
+ u_char *b_rptr; /* head pointer */
+ u_char *b_buf; /* data buffer */
+ u_char *b_lim; /* end of data buffer */
+};
+
+/* return the current length of the message */
+#define uni_msg_len(M) ((size_t)((M)->b_wptr - (M)->b_rptr))
+
+/* return the number of space behind the message */
+#define uni_msg_space(M) ((size_t)((M)->b_lim - (M)->b_wptr))
+
+/* return the amount of leading free space */
+#define uni_msg_leading(M) ((size_t)((M)->b_rptr - (M)->b_buf))
+
+/* return the maximum size of the message (length plus free space) */
+#define uni_msg_size(M) ((size_t)((M)->b_lim - (M)->b_buf));
+
+/* ensure that there is space for another S bytes. If reallocation fails
+ * free message and return -1 */
+#define uni_msg_ensure(M, S) \
+ ((uni_msg_space(M) >= (S)) ? 0 : uni_msg_extend(M, S))
+
+int uni_msg_append(struct uni_msg *, void *, size_t);
+int uni_msg_extend(struct uni_msg *, size_t);
+
+#define uni_msg_rptr(MSG, TYPE) ((TYPE)(void *)(MSG)->b_rptr)
+#define uni_msg_wptr(MSG, TYPE) ((TYPE)(void *)(MSG)->b_wptr)
+
+int uni_msg_prepend(struct uni_msg *, size_t);
+
+#ifndef _KERNEL
+
+struct uni_msg *uni_msg_alloc(size_t);
+struct uni_msg *uni_msg_build(void *, ...);
+void uni_msg_destroy(struct uni_msg *);
+u_int uni_msg_strip32(struct uni_msg *);
+u_int uni_msg_get32(struct uni_msg *);
+int uni_msg_append32(struct uni_msg *, u_int);
+int uni_msg_append8(struct uni_msg *, u_int);
+u_int uni_msg_trail32(const struct uni_msg *, int);
+struct uni_msg *uni_msg_dup(const struct uni_msg *);
+
+#endif /* _KERNEL */
+#endif