summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ngatm
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2003-11-03 09:05:49 +0000
committerharti <harti@FreeBSD.org>2003-11-03 09:05:49 +0000
commit521744184b372df4d3fce8716b4e983816c0fff0 (patch)
tree020b95a295456b19b53c8148dc295fbb23429b51 /sys/contrib/ngatm
parentf3021513b4a13988bf03f1dadeb8b5a5e96d63a9 (diff)
parentd2e4a0c64439be23c448c5da91bb2bbfa709d38c (diff)
downloadFreeBSD-src-521744184b372df4d3fce8716b4e983816c0fff0.zip
FreeBSD-src-521744184b372df4d3fce8716b4e983816c0fff0.tar.gz
This commit was generated by cvs2svn to compensate for changes in r121934,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'sys/contrib/ngatm')
-rw-r--r--sys/contrib/ngatm/netnatm/addr.h42
-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/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.h215
-rw-r--r--sys/contrib/ngatm/netnatm/msg/uni_ie.c7162
-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.h1370
20 files changed, 11628 insertions, 0 deletions
diff --git a/sys/contrib/ngatm/netnatm/addr.h b/sys/contrib/ngatm/netnatm/addr.h
new file mode 100644
index 0000000..9064d10
--- /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/atm/addr.h,v 1.2 2003/09/19 13:10:35 hbb 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/genfiles b/sys/contrib/ngatm/netnatm/genfiles
new file mode 100644
index 0000000..c1bc396
--- /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.
+#
+# $Begemot: libunimsg/atm/genfiles,v 1.3 2003/09/19 11:51:57 hbb Exp $
+#
+# Author: Harti Brandt <harti@freebsd.org>
+#
+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 0000000..78207aa
--- /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.
+ *
+ * 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/atm/misc/straddr.c,v 1.3 2003/09/19 12:05:45 hbb 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/msg/geniec.awk b/sys/contrib/ngatm/netnatm/msg/geniec.awk
new file mode 100644
index 0000000..8030c59
--- /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/atm/msg/geniec.awk,v 1.3 2003/09/19 11:58:15 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 0000000..8119b1d
--- /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/atm/msg/genieh.awk,v 1.3 2003/09/19 11:58:15 hbb 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 0000000..d3f196e
--- /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/atm/msg/genmsgc.awk,v 1.3 2003/09/19 11:58:15 hbb 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 0000000..a98fa98
--- /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/atm/msg/genmsgh.awk,v 1.3 2003/09/19 11:58:15 hbb 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 0000000..61c0ccf
--- /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/atm/msg/ie.def,v 1.3 2003/09/19 11:58:15 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 0000000..40099a4
--- /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/atm/msg/msg.def,v 1.3 2003/09/19 11:58:15 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 0000000..a505951
--- /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/atm/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 0000000..2414003
--- /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/atm/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 0000000..4894390
--- /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/atm/msg/priv.h,v 1.3 2003/09/19 11:58:15 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 0000000..3a3051a
--- /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/atm/msg/privmsg.c,v 1.3 2003/09/19 11:58:15 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;
+ 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
+ */
+ 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 */
+ UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_ACC);
+ else
+ 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 0000000..f941ded
--- /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/atm/msg/traffic.c,v 1.3 2003/09/19 11:58:15 hbb 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 0000000..2a16152
--- /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/atm/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 0000000..0447de6
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uni_hdr.h
@@ -0,0 +1,215 @@
+/*
+ * 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/atm/msg/uni_hdr.h,v 1.3 2003/09/19 11:58:15 hbb Exp $
+ */
+#ifndef _NETNATM_MSG_UNI_HDR_H_
+#define _NETNATM_MSG_UNI_HDR_H_
+
+#include <sys/types.h>
+
+#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 0000000..b6a2b78
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/uni_ie.c
@@ -0,0 +1,7162 @@
+/*
+ * 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/atm/msg/uni_ie.c,v 1.12 2003/10/14 15:02:22 hbb 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 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;
+
+ 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;
+
+ 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 (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 (ie->cause < 128 && tab1[ie->cause].str)
+ strcpy(buf, tab1[ie->cause].str);
+ else if (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 (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) {
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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;
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = cx; ie = 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)
+{
+ cx = cx; ie = 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)
+{
+ ie = ie; cx = 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;
+
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = cx;
+ ie = 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)
+{
+ cx = 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)
+{
+ cx = cx;
+
+ if(ie->vpi >= 1 << 12)
+ return -1;
+ return 0;
+}
+
+DEF_IE_CHECK(net, called_soft)
+{
+ cx = 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++;
+ } 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++;
+ } 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)
+{
+ cx = 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;
+
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = cx; ie = 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)
+{
+ cx = 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)
+{
+ cx = 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)
+{
+ cx = 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/unimsglib.h b/sys/contrib/ngatm/netnatm/msg/unimsglib.h
new file mode 100644
index 0000000..e98d580
--- /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/atm/msg/unimsglib.h,v 1.3 2003/09/19 11:58:16 hbb 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 0000000..c16f6b1
--- /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/atm/msg/uniprint.h,v 1.3 2003/09/19 11:58:16 hbb 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 0000000..fd57cf9
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/msg/unistruct.h
@@ -0,0 +1,1370 @@
+/*
+ * 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/atm/msg/unistruct.h,v 1.4 2003/09/19 11:58:16 hbb 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,
+};
+
+struct uni_addr {
+ enum uni_addr_type type;
+ enum uni_addr_plan plan;
+ u_int 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
OpenPOWER on IntegriCloud