summaryrefslogtreecommitdiffstats
path: root/sys/netatm/uni/unisig_encode.c
diff options
context:
space:
mode:
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