summaryrefslogtreecommitdiffstats
path: root/sys/netatm/uni/unisig_encode.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1998-09-15 08:23:17 +0000
committerphk <phk@FreeBSD.org>1998-09-15 08:23:17 +0000
commitc3dd1fa899d435ea4bf79897f646a93cb80c94ac (patch)
tree98dfbc96e3c6aa7ff1f322855f6484c4e609819d /sys/netatm/uni/unisig_encode.c
parent9ed6892f4808d56de443849229e151f8f7ad43b0 (diff)
downloadFreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.zip
FreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.tar.gz
Add new files for HARP3
Host ATM Research Platform (HARP), Network Computing Services, Inc. This software was developed with the support of the Defense Advanced Research Projects Agency (DARPA).
Diffstat (limited to 'sys/netatm/uni/unisig_encode.c')
-rw-r--r--sys/netatm/uni/unisig_encode.c1681
1 files changed, 1681 insertions, 0 deletions
diff --git a/sys/netatm/uni/unisig_encode.c b/sys/netatm/uni/unisig_encode.c
new file mode 100644
index 0000000..0920acc
--- /dev/null
+++ b/sys/netatm/uni/unisig_encode.c
@@ -0,0 +1,1681 @@
+/*
+ *
+ * ===================================
+ * HARP | Host ATM Research Platform
+ * ===================================
+ *
+ *
+ * This Host ATM Research Platform ("HARP") file (the "Software") is
+ * made available by Network Computing Services, Inc. ("NetworkCS")
+ * "AS IS". NetworkCS does not provide maintenance, improvements or
+ * support of any kind.
+ *
+ * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
+ * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
+ * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
+ * In no event shall NetworkCS be responsible for any damages, including
+ * but not limited to consequential damages, arising from or relating to
+ * any use of the Software or related support.
+ *
+ * Copyright 1994-1998 Network Computing Services, Inc.
+ *
+ * Copies of this Software may be made, however, the above copyright
+ * notice must be reproduced on all copies.
+ *
+ * @(#) $Id: unisig_encode.c,v 1.11 1998/08/26 23:29:21 mks Exp $
+ *
+ */
+
+/*
+ * ATM Forum UNI 3.0/3.1 Signalling Manager
+ * ----------------------------------------
+ *
+ * Message formatting module
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: unisig_encode.c,v 1.11 1998/08/26 23:29:21 mks Exp $";
+#endif
+
+#include <netatm/kern_include.h>
+
+#include <netatm/uni/unisig.h>
+#include <netatm/uni/unisig_var.h>
+#include <netatm/uni/unisig_msg.h>
+#include <netatm/uni/unisig_mbuf.h>
+#include <netatm/uni/unisig_decode.h>
+
+
+/*
+ * Local functions
+ */
+static int usf_enc_ie __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_aalp __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_clrt __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_bbcp __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_bhli __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_blli __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_clst __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_cdad __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_cdsa __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_cgad __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_cgsa __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_caus __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_cnid __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_qosp __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_brpi __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_rsti __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_bsdc __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_trnt __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_uimp __P((struct usfmt *, struct ie_generic *));
+static int usf_enc_ie_ident __P((struct usfmt *, struct ie_generic *,
+ struct ie_decode_tbl *));
+static int usf_enc_atm_addr __P((struct usfmt *, Atm_addr *));
+
+
+/*
+ * Local variables
+ */
+static struct {
+ u_char ident; /* IE identifier */
+ int (*encode) __P((struct usfmt *, struct ie_generic *));
+ /* Encoding function */
+} ie_table[] = {
+ { UNI_IE_AALP, usf_enc_ie_aalp },
+ { UNI_IE_CLRT, usf_enc_ie_clrt },
+ { UNI_IE_BBCP, usf_enc_ie_bbcp },
+ { UNI_IE_BHLI, usf_enc_ie_bhli },
+ { UNI_IE_BLLI, usf_enc_ie_blli },
+ { UNI_IE_CLST, usf_enc_ie_clst },
+ { UNI_IE_CDAD, usf_enc_ie_cdad },
+ { UNI_IE_CDSA, usf_enc_ie_cdsa },
+ { UNI_IE_CGAD, usf_enc_ie_cgad },
+ { UNI_IE_CGSA, usf_enc_ie_cgsa },
+ { UNI_IE_CAUS, usf_enc_ie_caus },
+ { UNI_IE_CNID, usf_enc_ie_cnid },
+ { UNI_IE_QOSP, usf_enc_ie_qosp },
+ { UNI_IE_BRPI, usf_enc_ie_brpi },
+ { UNI_IE_RSTI, usf_enc_ie_rsti },
+ { UNI_IE_BLSH, usf_enc_ie_uimp },
+ { UNI_IE_BNSH, usf_enc_ie_uimp },
+ { UNI_IE_BSDC, usf_enc_ie_bsdc },
+ { UNI_IE_TRNT, usf_enc_ie_trnt },
+ { UNI_IE_EPRF, usf_enc_ie_uimp },
+ { UNI_IE_EPST, usf_enc_ie_uimp },
+ { 0, 0 }
+};
+
+extern struct ie_decode_tbl ie_aal1_tbl[];
+extern struct ie_decode_tbl ie_aal4_tbl_30[];
+extern struct ie_decode_tbl ie_aal4_tbl_31[];
+extern struct ie_decode_tbl ie_aal5_tbl_30[];
+extern struct ie_decode_tbl ie_aal5_tbl_31[];
+extern struct ie_decode_tbl ie_clrt_tbl[];
+
+
+/*
+ * Encode a UNI signalling message
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * msg pointer to a signalling message structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+int
+usf_enc_msg(usf, msg)
+ struct usfmt *usf;
+ struct unisig_msg *msg;
+{
+ int i, len, rc;
+ u_char c;
+ u_char *lp0, *lp1;
+ struct ie_generic *ie;
+
+ union {
+ short s;
+ u_char sb[sizeof(short)];
+ } su;
+
+ ATM_DEBUG2("usf_enc_msg: usf=0x%x, msg=0x%x\n",
+ (int)usf, (int)msg);
+
+ /*
+ * Encode the protocol discriminator
+ */
+ c = UNI_MSG_DISC_Q93B;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode the call reference length
+ */
+ c = 3;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode the call reference
+ */
+ rc = usf_int3(usf, &msg->msg_call_ref);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode the message type
+ */
+ rc = usf_byte(usf, &msg->msg_type);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode the message type extension
+ */
+ c = ((msg->msg_type_flag & UNI_MSG_TYPE_FLAG_MASK) <<
+ UNI_MSG_TYPE_FLAG_SHIFT) +
+ (msg->msg_type_action & UNI_MSG_TYPE_ACT_MASK) +
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ /*
+ * Save the location of the message length and encode a length
+ * of zero for now. We'll fix the length up at the end.
+ */
+ su.s = 0;
+ rc = usf_byte_mark(usf, &su.sb[sizeof(short)-2], &lp0);
+ if (rc)
+ return(rc);
+ rc = usf_byte_mark(usf, &su.sb[sizeof(short)-1], &lp1);
+ if (rc)
+ return(rc);
+
+ /*
+ * Process information elements
+ */
+ len = 0;
+ for (i=0; i<UNI_MSG_IE_CNT; i++) {
+ ie = msg->msg_ie_vec[i];
+ while (ie) {
+ rc = usf_enc_ie(usf, ie);
+ if (rc)
+ return(rc);
+ len += (ie->ie_length + UNI_IE_HDR_LEN);
+ ie = ie->ie_next;
+ }
+ }
+
+ /*
+ * Fix the message length in the encoded message
+ */
+ su.s = htons((u_short)len);
+ *lp0 = su.sb[sizeof(short)-2];
+ *lp1 = su.sb[sizeof(short)-1];
+
+ return(0);
+}
+
+
+/*
+ * Encode an information element
+ *
+ * Arguments:
+ * usf pointer to a UNISIG formatting structure
+ * msg pointer to a UNISIG message structure
+ * ie pointer to a generic IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int i, rc;
+ u_char c;
+ u_char *lp0, *lp1;
+
+ union {
+ short s;
+ u_char sb[sizeof(short)];
+ } su;
+
+ ATM_DEBUG2("usf_enc_ie: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ /*
+ * Encode the IE identifier
+ */
+ rc = usf_byte(usf, &ie->ie_ident);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode the extended type
+ */
+ c = ((ie->ie_coding & UNI_IE_CODE_MASK) << UNI_IE_CODE_SHIFT) +
+ ((ie->ie_flag & UNI_IE_FLAG_MASK) <<
+ UNI_IE_FLAG_SHIFT) +
+ (ie->ie_action & UNI_IE_ACT_MASK) +
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ /*
+ * Mark the current location in the output stream. Encode a
+ * length of zero for now; we'll come back and fix it up at
+ * the end.
+ */
+ su.s = 0;
+ rc = usf_byte_mark(usf, &su.sb[sizeof(short)-2], &lp0);
+ if (rc)
+ return(rc);
+ rc = usf_byte_mark(usf, &su.sb[sizeof(short)-1], &lp1);
+ if (rc)
+ return(rc);
+
+ /*
+ * Look up the information element in the table
+ */
+ for (i=0; (ie->ie_ident != ie_table[i].ident) &&
+ (ie_table[i].encode != NULL); i++) {
+ }
+ if (ie_table[i].encode == NULL) {
+ /*
+ * Unrecognized IE
+ */
+ return(EINVAL);
+ }
+
+ /*
+ * Process the IE by calling the function indicated
+ * in the IE table
+ */
+ rc = ie_table[i].encode(usf, ie);
+ if (rc)
+ return(rc);
+
+ /*
+ * Set the length in the output stream
+ */
+ su.s = htons((u_short)ie->ie_length);
+ *lp0 = su.sb[sizeof(short)-2];
+ *lp1 = su.sb[sizeof(short)-1];
+
+ return(0);
+}
+
+
+/*
+ * Encode an AAL parameters information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to an AAL parms IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_aalp(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int i, rc = 0;
+
+ ATM_DEBUG2("usf_enc_ie_aalp: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ ie->ie_length = 0;
+
+ /*
+ * Encode the AAL type
+ */
+ if (ie->ie_aalp_aal_type == T_ATM_ABSENT)
+ return(0);
+ rc = usf_byte(usf, &ie->ie_aalp_aal_type);
+ if (rc)
+ return(rc);
+
+ /*
+ * Process based on AAL type
+ */
+ switch (ie->ie_aalp_aal_type) {
+ case UNI_IE_AALP_AT_AAL1:
+ rc = usf_enc_ie_ident(usf, ie, ie_aal1_tbl);
+ break;
+ case UNI_IE_AALP_AT_AAL3:
+ if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
+ rc = usf_enc_ie_ident(usf, ie, ie_aal4_tbl_30);
+ else
+ rc = usf_enc_ie_ident(usf, ie, ie_aal4_tbl_31);
+ break;
+ case UNI_IE_AALP_AT_AAL5:
+ if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
+ rc = usf_enc_ie_ident(usf, ie, ie_aal5_tbl_30);
+ else
+ rc = usf_enc_ie_ident(usf, ie, ie_aal5_tbl_31);
+ break;
+ case UNI_IE_AALP_AT_AALU:
+ /*
+ * Encode the user data
+ */
+ i = 0;
+ while (i < sizeof(ie->ie_aalp_user_info)) {
+ rc = usf_byte(usf, &ie->ie_aalp_user_info[i]);
+ if (rc)
+ break;
+ i++;
+ ie->ie_length++;
+ }
+ break;
+ default:
+ return(EINVAL);
+ }
+
+ ie->ie_length++;
+ return(rc);
+}
+
+
+/*
+ * Encode a user cell rate information element
+ *
+ * This routine just encodes the parameters required for best
+ * effort service.
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_clrt(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int rc;
+
+ ATM_DEBUG2("usf_enc_ie_clrt: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+#ifdef NOTDEF
+ /*
+ * Encode Peak Cell Rate Forward CLP = 0 + 1
+ */
+ c = UNI_IE_CLRT_FWD_PEAK_01_ID;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ rc = usf_int3(usf, &ie->ie_clrt_fwd_peak_01);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode Peak Cell Rate Backward CLP = 0 + 1
+ */
+ c = UNI_IE_CLRT_BKWD_PEAK_01_ID;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ rc = usf_int3(usf, &ie->ie_clrt_bkwd_peak_01);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode Best Effort Flag
+ */
+ c = UNI_IE_CLRT_BEST_EFFORT_ID;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ /*
+ * Set IE length
+ */
+ ie->ie_length = 9;
+#endif
+
+ /*
+ * Encode the user cell rate IE using the table
+ */
+ ie->ie_length = 0;
+ rc = usf_enc_ie_ident(usf, ie, ie_clrt_tbl);
+
+ return(rc);
+}
+
+
+/*
+ * Encode a broadband bearer capability information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_bbcp(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int rc;
+ u_char c;
+
+ ATM_DEBUG2("usf_enc_ie_bbcp: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ ie->ie_length = 0;
+
+ /*
+ * Encode the broadband bearer class
+ */
+ if (ie->ie_bbcp_bearer_class == T_ATM_ABSENT)
+ return(0);
+ c = ie->ie_bbcp_bearer_class & UNI_IE_BBCP_BC_MASK;
+ if (ie->ie_bbcp_bearer_class != UNI_IE_BBCP_BC_BCOB_X)
+ c |= UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ /*
+ * If the broadband bearer class was X, the next
+ * byte has the traffic type and timing requirements
+ */
+ if (ie->ie_bbcp_bearer_class == UNI_IE_BBCP_BC_BCOB_X) {
+ c = ((ie->ie_bbcp_traffic_type & UNI_IE_BBCP_TT_MASK) <<
+ UNI_IE_BBCP_TT_SHIFT) +
+ (ie->ie_bbcp_timing_req &
+ UNI_IE_BBCP_TR_MASK) +
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+
+ /*
+ * Encode the clipping and user plane connection configuration
+ */
+ c = ((ie->ie_bbcp_clipping & UNI_IE_BBCP_SC_MASK) <<
+ UNI_IE_BBCP_SC_SHIFT) +
+ (ie->ie_bbcp_conn_config &
+ UNI_IE_BBCP_CC_MASK) +
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ return(0);
+}
+
+
+/*
+ * Encode a broadband high layer information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_bhli(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int i, rc;
+ u_int type;
+
+ ATM_DEBUG2("usf_enc_ie_bhli: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ ie->ie_length = 0;
+
+ /*
+ * Encode the high layer information type
+ */
+ if (ie->ie_bhli_type == T_ATM_ABSENT)
+ return(0);
+ type = ie->ie_bhli_type | UNI_IE_EXT_BIT;
+ rc = usf_ext(usf, &type);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ /*
+ * What comes next depends on the type
+ */
+ switch (ie->ie_bhli_type) {
+ case UNI_IE_BHLI_TYPE_ISO:
+ case UNI_IE_BHLI_TYPE_USER:
+ /*
+ * ISO or user-specified parameters -- take the
+ * length of information from the IE length
+ */
+ for (i=0; i<ie->ie_length-1; i++) {
+ rc = usf_byte(usf, &ie->ie_bhli_info[i]);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+ break;
+ case UNI_IE_BHLI_TYPE_HLP:
+ /*
+ * Make sure the IE is long enough for the high
+ * layer profile information, then get it
+ */
+ if (usf->usf_sig->us_proto != ATM_SIG_UNI30)
+ return (EINVAL);
+ for (i=0; i<UNI_IE_BHLI_HLP_LEN; i++) {
+ rc = usf_byte(usf, &ie->ie_bhli_info[i]);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+ break;
+ case UNI_IE_BHLI_TYPE_VSA:
+ /*
+ * Make sure the IE is long enough for the vendor-
+ * specific application information, then get it
+ */
+ for (i=0; i<UNI_IE_BHLI_VSA_LEN; i++) {
+ rc = usf_byte(usf, &ie->ie_bhli_info[i]);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+ break;
+ default:
+ return(EINVAL);
+ }
+
+ return(0);
+}
+
+
+/*
+ * Encode a broadband low layer information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_blli(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ u_char c;
+ int rc;
+ u_int ipi;
+
+ ATM_DEBUG2("usf_enc_ie_blli: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ ie->ie_length = 0;
+
+ /*
+ * Encode paramteters for whichever protocol layers the
+ * user specified
+ */
+
+ /*
+ * Layer 1 information
+ */
+ if (ie->ie_blli_l1_id && ie->ie_blli_l1_id != T_ATM_ABSENT) {
+ c = (UNI_IE_BLLI_L1_ID << UNI_IE_BLLI_LID_SHIFT) +
+ (ie->ie_blli_l1_id &
+ UNI_IE_BLLI_LP_MASK) +
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+
+ /*
+ * Layer 2 information
+ */
+ if (ie->ie_blli_l2_id && ie->ie_blli_l2_id != T_ATM_ABSENT) {
+ c = (UNI_IE_BLLI_L2_ID << UNI_IE_BLLI_LID_SHIFT) +
+ (ie->ie_blli_l2_id &
+ UNI_IE_BLLI_LP_MASK);
+
+ switch (ie->ie_blli_l2_id) {
+ case UNI_IE_BLLI_L2P_X25L:
+ case UNI_IE_BLLI_L2P_X25M:
+ case UNI_IE_BLLI_L2P_HDLC1:
+ case UNI_IE_BLLI_L2P_HDLC2:
+ case UNI_IE_BLLI_L2P_HDLC3:
+ case UNI_IE_BLLI_L2P_Q922:
+ case UNI_IE_BLLI_L2P_ISO7776:
+ /*
+ * Write the Layer 2 type
+ */
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ /*
+ * Encode the Layer 2 mode
+ */
+ if (ie->ie_blli_l2_mode) {
+ c = (ie->ie_blli_l2_mode &
+ UNI_IE_BLLI_L2MODE_MASK) <<
+ UNI_IE_BLLI_L2MODE_SHIFT;
+ if (!ie->ie_blli_l2_window)
+ c |= UNI_IE_EXT_BIT;
+
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+
+ /*
+ * Encode the Layer 2 window size
+ */
+ if (ie->ie_blli_l2_window) {
+ c = (ie->ie_blli_l2_window &
+ UNI_IE_EXT_MASK) +
+ UNI_IE_EXT_BIT;
+
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+ break;
+ case UNI_IE_BLLI_L2P_USER:
+ /*
+ * Write the Layer 2 type
+ */
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ /*
+ * Encode the user-specified layer 2 info
+ */
+ c = (ie->ie_blli_l2_user_proto &
+ UNI_IE_EXT_MASK) +
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ break;
+ default:
+ /*
+ * Write the Layer 2 type
+ */
+ c |= UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ break;
+ }
+ }
+
+ /*
+ * Layer 3 information
+ */
+ if (ie->ie_blli_l3_id && ie->ie_blli_l3_id != T_ATM_ABSENT) {
+ /*
+ * Encode the layer 3 protocol ID
+ */
+ c = (UNI_IE_BLLI_L3_ID << UNI_IE_BLLI_LID_SHIFT) +
+ (ie->ie_blli_l3_id &
+ UNI_IE_BLLI_LP_MASK);
+
+ /*
+ * Process other fields based on protocol ID
+ */
+ switch(ie->ie_blli_l3_id) {
+ case UNI_IE_BLLI_L3P_X25:
+ case UNI_IE_BLLI_L3P_ISO8208:
+ case UNI_IE_BLLI_L3P_ISO8878:
+ /*
+ * Write the protocol ID
+ */
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ if (ie->ie_blli_l3_mode ||
+ ie->ie_blli_l3_packet_size ||
+ ie->ie_blli_l3_window) {
+ c = (ie->ie_blli_l3_mode &
+ UNI_IE_BLLI_L3MODE_MASK) <<
+ UNI_IE_BLLI_L3MODE_SHIFT;
+ if (!ie->ie_blli_l3_packet_size &&
+ !ie->ie_blli_l3_window)
+ c |= UNI_IE_EXT_BIT;
+
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+
+ if (ie->ie_blli_l3_packet_size ||
+ ie->ie_blli_l3_window) {
+ c = ie->ie_blli_l3_packet_size &
+ UNI_IE_BLLI_L3PS_MASK;
+ if (!ie->ie_blli_l3_window)
+ c |= UNI_IE_EXT_BIT;
+
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+
+ if (ie->ie_blli_l3_window) {
+ c = (ie->ie_blli_l3_window &
+ UNI_IE_EXT_MASK) +
+ UNI_IE_EXT_BIT;
+
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+ break;
+ case UNI_IE_BLLI_L3P_USER:
+ /*
+ * Write the protocol ID
+ */
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ /*
+ * Encode the user-specified protocol info
+ */
+ c = (ie->ie_blli_l3_user_proto &
+ UNI_IE_EXT_MASK) +
+ UNI_IE_EXT_BIT;
+
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ break;
+ case UNI_IE_BLLI_L3P_ISO9577:
+ /*
+ * Write the protocol ID
+ */
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ /*
+ * Encode the IPI
+ */
+ ipi = ie->ie_blli_l3_ipi <<
+ UNI_IE_BLLI_L3IPI_SHIFT;
+ rc = usf_ext(usf, &ipi);
+ if (rc)
+ return(rc);
+ ie->ie_length += 2;
+
+ if (ie->ie_blli_l3_ipi ==
+ UNI_IE_BLLI_L3IPI_SNAP) {
+ c = UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ rc = usf_byte(usf,
+ &ie->ie_blli_l3_oui[0]);
+ if (rc)
+ return(rc);
+
+ rc = usf_byte(usf,
+ &ie->ie_blli_l3_oui[1]);
+ if (rc)
+ return(rc);
+
+ rc = usf_byte(usf,
+ &ie->ie_blli_l3_oui[2]);
+ if (rc)
+ return(rc);
+
+ rc = usf_byte(usf,
+ &ie->ie_blli_l3_pid[0]);
+ if (rc)
+ return(rc);
+
+ rc = usf_byte(usf,
+ &ie->ie_blli_l3_pid[1]);
+ if (rc)
+ return(rc);
+
+ ie->ie_length += 6;
+ }
+ break;
+ default:
+ /*
+ * Write the layer 3 protocol ID
+ */
+ c |= UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ break;
+ }
+ }
+
+ return(0);
+}
+
+
+/*
+ * Encode a call state information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_clst(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int rc;
+ u_char c;
+
+ ATM_DEBUG2("usf_enc_ie_clst: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ c = ie->ie_clst_state & UNI_IE_CLST_STATE_MASK;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length = 1;
+
+ return(0);
+}
+
+
+/*
+ * Encode a called party number information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_cdad(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ u_char c;
+ int rc;
+
+ ATM_DEBUG2("usf_enc_ie_cdad: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ /*
+ * Encode the numbering plan
+ */
+ switch(ie->ie_cdad_addr.address_format) {
+ case T_ATM_E164_ADDR:
+ c = UNI_IE_CDAD_PLAN_E164 +
+ (UNI_IE_CDAD_TYPE_INTL
+ << UNI_IE_CDAD_TYPE_SHIFT);
+ ie->ie_length = sizeof(Atm_addr_e164) + 1;
+ break;
+ case T_ATM_ENDSYS_ADDR:
+ c = UNI_IE_CDAD_PLAN_NSAP +
+ (UNI_IE_CDAD_TYPE_UNK
+ << UNI_IE_CDAD_TYPE_SHIFT);
+ ie->ie_length = sizeof(Atm_addr_nsap) + 1;
+ break;
+ default:
+ return(EINVAL);
+ }
+ c |= UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode the ATM address
+ */
+ rc = usf_enc_atm_addr(usf, &ie->ie_cdad_addr);
+
+ return(rc);
+}
+
+
+/*
+ * Encode a called party subaddress information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_cdsa(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ u_char c;
+ int rc;
+
+ /*
+ * Encode the subaddress type
+ */
+ switch(ie->ie_cdsa_addr.address_format) {
+ case T_ATM_ENDSYS_ADDR:
+ c = UNI_IE_CDSA_TYPE_AESA << UNI_IE_CDSA_TYPE_SHIFT;
+ ie->ie_length = sizeof(Atm_addr_nsap) + 1;
+ break;
+ default:
+ return(EINVAL);
+ }
+ c |= UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode the ATM address
+ */
+ rc = usf_enc_atm_addr(usf, &ie->ie_cdsa_addr);
+
+ return(rc);
+}
+
+
+/*
+ * Encode a calling party number information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_cgad(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ u_char c;
+ int rc;
+
+ ATM_DEBUG2("usf_enc_ie_cgad: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ /*
+ * Encode the numbering plan
+ */
+ switch(ie->ie_cgad_addr.address_format) {
+ case T_ATM_E164_ADDR:
+ c = UNI_IE_CGAD_PLAN_E164 +
+ (UNI_IE_CGAD_TYPE_INTL
+ << UNI_IE_CGAD_TYPE_SHIFT) +
+ UNI_IE_EXT_BIT;
+ ie->ie_length = sizeof(Atm_addr_e164) + 1;
+ break;
+ case T_ATM_ENDSYS_ADDR:
+ c = UNI_IE_CGAD_PLAN_NSAP +
+ (UNI_IE_CGAD_TYPE_UNK
+ << UNI_IE_CGAD_TYPE_SHIFT) +
+ UNI_IE_EXT_BIT;
+ ie->ie_length = sizeof(Atm_addr_nsap) + 1;
+ break;
+ default:
+ return(EINVAL);
+ }
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode the presentation and screening indicators
+ */
+#ifdef NOTDEF
+ c = ((ie->ie_cgad_pres_ind & UNI_IE_CGAD_PRES_MASK)
+ << UNI_IE_CGAD_PRES_SHIFT) +
+ (ie->ie_cgad_screen_ind &
+ UNI_IE_CGAD_SCR_MASK) +
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+#endif
+
+
+ /*
+ * Encode the ATM address
+ */
+ rc = usf_enc_atm_addr(usf, &ie->ie_cgad_addr);
+
+ return(rc);
+}
+
+
+/*
+ * Encode a calling party subaddress information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_cgsa(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ u_char c;
+ int rc;
+
+ /*
+ * Encode the subaddress type
+ */
+ switch(ie->ie_cgsa_addr.address_format) {
+ case T_ATM_ENDSYS_ADDR:
+ c = UNI_IE_CGSA_TYPE_AESA << UNI_IE_CGSA_TYPE_SHIFT;
+ ie->ie_length = sizeof(Atm_addr_nsap) + 1;
+ break;
+ default:
+ return(EINVAL);
+ }
+ c |= UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode the ATM address
+ */
+ rc = usf_enc_atm_addr(usf, &ie->ie_cgsa_addr);
+
+ return(rc);
+}
+
+
+/*
+ * Encode a cause information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_caus(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int i, rc;
+ u_char c;
+
+ ATM_DEBUG2("usf_enc_ie_caus: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ ie->ie_length = 0;
+
+ /*
+ * Encode the cause location
+ */
+ c = (ie->ie_caus_loc & UNI_IE_CAUS_LOC_MASK) | UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ /*
+ * Encode the cause value
+ */
+ c = ie->ie_caus_cause | UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+
+ /*
+ * Encode any included diagnostics
+ */
+ for (i = 0; i < ie->ie_caus_diag_len &&
+ i < sizeof(ie->ie_caus_diagnostic);
+ i++) {
+ rc = usf_byte(usf, &ie->ie_caus_diagnostic[i]);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+
+ return(0);
+}
+
+
+/*
+ * Encode a conection identifier information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_cnid(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int rc;
+ u_char c;
+
+ ATM_DEBUG2("usf_enc_ie_cnid: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ c = ((ie->ie_cnid_vp_sig & UNI_IE_CNID_VPSIG_MASK)
+ << UNI_IE_CNID_VPSIG_SHIFT) +
+ (ie->ie_cnid_pref_excl & UNI_IE_CNID_PREX_MASK) +
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+
+ rc = usf_short(usf, &ie->ie_cnid_vpci);
+ if (rc)
+ return(rc);
+ rc = usf_short(usf, &ie->ie_cnid_vci);
+ if (rc)
+ return(rc);
+
+ ie->ie_length = 5;
+ return(0);
+}
+
+
+/*
+ * Encode a quality of service parameters information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_qosp(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int rc;
+
+ ATM_DEBUG2("usf_enc_ie_qosp: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ /*
+ * Encode forward QoS class
+ */
+ if (ie->ie_qosp_fwd_class == T_ATM_ABSENT ||
+ ie->ie_qosp_bkwd_class == T_ATM_ABSENT)
+ return(0);
+ rc = usf_byte(usf, &ie->ie_qosp_fwd_class);
+ if (rc)
+ return(rc);
+
+ /*
+ * Encode backward QoS class
+ */
+ rc = usf_byte(usf, &ie->ie_qosp_bkwd_class);
+
+ ie->ie_length = 2;
+ return(rc);
+}
+
+
+/*
+ * Encode a broadband repeat indicator information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_brpi(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int rc;
+ u_char c;
+
+ ATM_DEBUG2("usf_enc_ie_brpi: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ /*
+ * Encode the repeat indicator
+ */
+ c = ie->ie_brpi_ind + UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+
+ return(rc);
+}
+
+
+/*
+ * Encode a restart indicator information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_rsti(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int rc;
+ u_char c;
+
+ ATM_DEBUG2("usf_enc_ie_rsti: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ /*
+ * Encode the restart class
+ */
+ c = (ie->ie_rsti_class & UNI_IE_RSTI_CLASS_MASK) |
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ ie->ie_length = 1;
+
+ return(rc);
+}
+
+
+/*
+ * Encode a broadband sending complete information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a broadband sending complete IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_bsdc(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int rc;
+ u_char c;
+
+ ATM_DEBUG2("usf_enc_ie_bsdc: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ /*
+ * Encode the sending complete indicator
+ */
+ c = UNI_IE_BSDC_IND | UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ ie->ie_length = 1;
+
+ return(rc);
+}
+
+
+/*
+ * Encode a transit network selection information element
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a transit network selection rate IE structure
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_trnt(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ int i, rc;
+ u_char c;
+
+ ATM_DEBUG2("usf_enc_ie_trnt: usf=0x%x, ie=0x%x\n",
+ (int)usf, (int)ie);
+
+ /*
+ * Encode the sending complete indicator
+ */
+ c = ((ie->ie_trnt_id_type & UNI_IE_TRNT_IDT_MASK) <<
+ UNI_IE_TRNT_IDT_SHIFT) +
+ (ie->ie_trnt_id_plan & UNI_IE_TRNT_IDP_MASK) +
+ UNI_IE_EXT_BIT;
+ rc = usf_byte(usf, &c);
+ if (rc)
+ return(rc);
+ ie->ie_length = 1;
+
+ /*
+ * Encode the network identification
+ */
+ for (i=0; i<ie->ie_trnt_id_len; i++) {
+ rc = usf_byte(usf, &ie->ie_trnt_id[i]);
+ if (rc)
+ return(rc);
+ ie->ie_length++;
+ }
+
+ return(rc);
+}
+
+
+/*
+ * Encode an unsupported IE type
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to an IE structure
+ *
+ * Returns:
+ * 0 success
+ *
+ */
+static int
+usf_enc_ie_uimp(usf, ie)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+{
+ return(0);
+}
+
+
+/*
+ * Encode an information element using field identifiers
+ *
+ * The AAL parameters and ATM user cell rate IEs are formatted
+ * with a one-byte identifier preceeding each field. The routine
+ * encodes these IEs by using a table which relates the field
+ * identifiers with the fields in the appropriate IE structure.
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * ie pointer to a cell rate IE structure
+ * tbl pointer to an IE decoding table
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_ie_ident(usf, ie, tbl)
+ struct usfmt *usf;
+ struct ie_generic *ie;
+ struct ie_decode_tbl *tbl;
+{
+ int i, len, rc;
+ char *cp;
+ u_int8_t cv;
+ u_int16_t sv;
+ u_int32_t iv;
+
+ ATM_DEBUG3("usf_enc_ie_ident: usf=0x%x, ie=0x%x, tbl=0x%x\n",
+ (int)usf, (int)ie, (int)tbl);
+
+ /*
+ * Scan through the IE table
+ */
+ len = 0;
+ for (i=0; tbl[i].ident; i++) {
+ /*
+ * Check whether to send the field
+ */
+ cp = (char *) ((int)ie + tbl[i].f_offs);
+ if (tbl[i].len == 0) {
+ if ((*cp == T_NO || *cp == T_ATM_ABSENT))
+ continue;
+ } else {
+ switch (tbl[i].f_size) {
+ case 1:
+ if (*(int8_t *)cp == T_ATM_ABSENT)
+ continue;
+ break;
+ case 2:
+ if (*(int16_t *)cp == T_ATM_ABSENT)
+ continue;
+ break;
+ case 4:
+ if (*(int32_t *)cp == T_ATM_ABSENT)
+ continue;
+ break;
+ default:
+badtbl:
+ log(LOG_ERR,
+ "uni encode: id=%d,len=%d,off=%d,size=%d\n",
+ tbl[i].ident, tbl[i].len,
+ tbl[i].f_offs, tbl[i].f_size);
+ return (EFAULT);
+ }
+ }
+
+ /*
+ * Encode the field identifier
+ */
+ rc = usf_byte(usf, &tbl[i].ident);
+ if (rc)
+ return(rc);
+ len++;
+
+ /*
+ * Encode the field value
+ */
+ switch (tbl[i].len) {
+ case 0:
+ break;
+ case 1:
+ switch (tbl[i].f_size) {
+ case 1:
+ cv = *(u_int8_t *)cp;
+ break;
+ case 2:
+ cv = *(u_int16_t *)cp;
+ break;
+ case 4:
+ cv = *(u_int32_t *)cp;
+ break;
+ default:
+ goto badtbl;
+ }
+ rc = usf_byte(usf, &cv);
+ break;
+
+ case 2:
+ switch (tbl[i].f_size) {
+ case 2:
+ sv = *(u_int16_t *)cp;
+ break;
+ case 4:
+ sv = *(u_int32_t *)cp;
+ break;
+ default:
+ goto badtbl;
+ }
+ rc = usf_short(usf, &sv);
+ break;
+
+ case 3:
+ switch (tbl[i].f_size) {
+ case 4:
+ iv = *(u_int32_t *)cp;
+ break;
+ default:
+ goto badtbl;
+ }
+ rc = usf_int3(usf, &iv);
+ break;
+
+ case 4:
+ switch (tbl[i].f_size) {
+ case 4:
+ iv = *(u_int32_t *)cp;
+ break;
+ default:
+ goto badtbl;
+ }
+ rc = usf_int(usf, &iv);
+ break;
+
+ default:
+ goto badtbl;
+ }
+
+ len += tbl[i].len;
+
+ if (rc)
+ return(rc);
+ }
+
+ ie->ie_length = len;
+ return(0);
+}
+
+
+/*
+ * Encode an ATM address
+ *
+ * Arguments:
+ * usf pointer to a unisig formatting structure
+ * addr pointer to an ATM address structure. The address
+ * type must already be set correctly.
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+usf_enc_atm_addr(usf, addr)
+ struct usfmt *usf;
+ Atm_addr *addr;
+{
+ int len, rc;
+ u_char *cp;
+
+ /*
+ * Check the address type
+ */
+ switch (addr->address_format) {
+ case T_ATM_E164_ADDR:
+ cp = (u_char *) addr->address;
+ len = sizeof(Atm_addr_e164);
+ break;
+ case T_ATM_ENDSYS_ADDR:
+ cp = (u_char *) addr->address;
+ len = sizeof(Atm_addr_nsap);
+ break;
+ default:
+ return(EINVAL);
+ }
+
+ /*
+ * Get the address bytes
+ */
+ while (len) {
+ rc = usf_byte(usf, cp);
+ if (rc)
+ return(rc);
+ len--;
+ cp++;
+ }
+
+ return(0);
+}
OpenPOWER on IntegriCloud