93e31e2f3c
Submitted by: Mike Spengler <mks@circe.networkcs.com>
1311 lines
33 KiB
C
1311 lines
33 KiB
C
/*
|
|
*
|
|
* ===================================
|
|
* 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_subr.c,v 1.4 1998/10/31 20:08:03 phk Exp $
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* ATM Forum UNI 3.0/3.1 Signalling Manager
|
|
* ----------------------------------------
|
|
*
|
|
* Subroutines
|
|
*
|
|
*/
|
|
|
|
#include <netatm/kern_include.h>
|
|
|
|
#include <netatm/uni/unisig.h>
|
|
#include <netatm/uni/unisig_var.h>
|
|
#include <netatm/uni/unisig_msg.h>
|
|
|
|
#ifndef lint
|
|
__RCSID("@(#) $Id: unisig_subr.c,v 1.4 1998/10/31 20:08:03 phk Exp $");
|
|
#endif
|
|
|
|
|
|
/*
|
|
* External variables
|
|
*/
|
|
extern struct ie_aalp ie_aalp_absent;
|
|
extern struct ie_clrt ie_clrt_absent;
|
|
extern struct ie_bbcp ie_bbcp_absent;
|
|
extern struct ie_bhli ie_bhli_absent;
|
|
extern struct ie_blli ie_blli_absent;
|
|
extern struct ie_clst ie_clst_absent;
|
|
extern struct ie_cdad ie_cdad_absent;
|
|
extern struct ie_cdsa ie_cdsa_absent;
|
|
extern struct ie_cgad ie_cgad_absent;
|
|
extern struct ie_cgsa ie_cgsa_absent;
|
|
extern struct ie_caus ie_caus_absent;
|
|
extern struct ie_cnid ie_cnid_absent;
|
|
extern struct ie_qosp ie_qosp_absent;
|
|
extern struct ie_brpi ie_brpi_absent;
|
|
extern struct ie_rsti ie_rsti_absent;
|
|
extern struct ie_blsh ie_blsh_absent;
|
|
extern struct ie_bnsh ie_bnsh_absent;
|
|
extern struct ie_bsdc ie_bsdc_absent;
|
|
extern struct ie_trnt ie_trnt_absent;
|
|
extern struct ie_eprf ie_eprf_absent;
|
|
extern struct ie_epst ie_epst_absent;
|
|
|
|
|
|
/*
|
|
* Set a User Location cause code in an ATM attribute block
|
|
*
|
|
* Arguments:
|
|
* aap pointer to attribute block
|
|
* cause cause code
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
unisig_cause_attr_from_user(aap, cause)
|
|
Atm_attributes *aap;
|
|
int cause;
|
|
{
|
|
if (cause == T_ATM_ABSENT)
|
|
return;
|
|
|
|
/*
|
|
* Set the fields in the attribute block
|
|
*/
|
|
aap->cause.tag = T_ATM_PRESENT;
|
|
aap->cause.v.coding_standard = T_ATM_ITU_CODING;
|
|
aap->cause.v.location = T_ATM_LOC_USER;
|
|
aap->cause.v.cause_value = cause;
|
|
KM_ZERO(aap->cause.v.diagnostics,
|
|
sizeof(aap->cause.v.diagnostics));
|
|
}
|
|
|
|
|
|
/*
|
|
* Set a cause code in an ATM attribute block from a Cause IE
|
|
*
|
|
* Arguments:
|
|
* aap pointer to attribute block
|
|
* iep pointer to Cause IE
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
unisig_cause_attr_from_ie(aap, iep)
|
|
Atm_attributes *aap;
|
|
struct ie_generic *iep;
|
|
{
|
|
/*
|
|
* Set the fields in the attribute block
|
|
*/
|
|
aap->cause.tag = T_ATM_PRESENT;
|
|
aap->cause.v.coding_standard = iep->ie_coding;
|
|
aap->cause.v.location = iep->ie_caus_loc;
|
|
aap->cause.v.cause_value = iep->ie_caus_cause;
|
|
KM_ZERO(aap->cause.v.diagnostics, sizeof(aap->cause.v.diagnostics));
|
|
KM_COPY(iep->ie_caus_diagnostic, aap->cause.v.diagnostics,
|
|
MIN(sizeof(aap->cause.v.diagnostics), iep->ie_caus_diag_len));
|
|
}
|
|
|
|
|
|
/*
|
|
* Open a UNI VCC
|
|
*
|
|
* Called when a user wants to open a VC. This function will construct
|
|
* a VCCB and, if we are opening an SVC, call the Q.2931 VC state
|
|
* machine. The user will have to wait for a notify event to be sure
|
|
* the SVC is fully open.
|
|
*
|
|
* Must be called at splnet.
|
|
*
|
|
* Arguments:
|
|
* usp pointer to UNISIG protocol instance
|
|
* cvp pointer to connection parameters for the VCC
|
|
*
|
|
* Returns:
|
|
* 0 VCC creation successful
|
|
* errno VCC setup failed - reason indicated
|
|
*
|
|
*/
|
|
int
|
|
unisig_open_vcc(usp, cvp)
|
|
struct unisig *usp;
|
|
Atm_connvc *cvp;
|
|
{
|
|
struct atm_pif *pip = usp->us_pif;
|
|
struct unisig_vccb *uvp;
|
|
Atm_addr_pvc *pvp;
|
|
int err, pvc;
|
|
|
|
ATM_DEBUG2("unisig_open_vcc: usp=%p, cvp=%p\n", usp, cvp);
|
|
|
|
/*
|
|
* Validate user parameters. AAL and encapsulation are
|
|
* checked by the connection manager
|
|
*/
|
|
|
|
/*
|
|
* Check called party address(es)
|
|
*/
|
|
if(cvp->cvc_attr.called.tag != T_ATM_PRESENT ||
|
|
cvp->cvc_attr.called.addr.address_format ==
|
|
T_ATM_ABSENT) {
|
|
return(EINVAL);
|
|
}
|
|
switch (cvp->cvc_attr.called.addr.address_format) {
|
|
case T_ATM_PVC_ADDR:
|
|
/*
|
|
* Make sure VPI/VCI is valid
|
|
*/
|
|
pvc = 1;
|
|
pvp = (Atm_addr_pvc *)cvp->cvc_attr.called.addr.address;
|
|
if ((ATM_PVC_GET_VPI(pvp) > pip->pif_maxvpi) ||
|
|
(ATM_PVC_GET_VCI(pvp) == 0) ||
|
|
(ATM_PVC_GET_VCI(pvp) > pip->pif_maxvci)) {
|
|
return(ERANGE);
|
|
}
|
|
|
|
/*
|
|
* Make sure VPI/VCI is not already in use
|
|
*/
|
|
if (unisig_find_vpvc(usp,
|
|
ATM_PVC_GET_VPI(pvp),
|
|
ATM_PVC_GET_VCI(pvp), 0)) {
|
|
return(EEXIST);
|
|
}
|
|
ATM_DEBUG2("unisig_open_vcc: VPI.VCI=%d.%d\n",
|
|
ATM_PVC_GET_VPI(pvp),
|
|
ATM_PVC_GET_VCI(pvp));
|
|
break;
|
|
|
|
case T_ATM_ENDSYS_ADDR:
|
|
/*
|
|
* Check signalling state
|
|
*/
|
|
pvc = 0;
|
|
pvp = NULL;
|
|
if (usp->us_state != UNISIG_ACTIVE) {
|
|
return(ENETDOWN);
|
|
}
|
|
|
|
/*
|
|
* Make sure there's no subaddress
|
|
*/
|
|
if (cvp->cvc_attr.called.subaddr.address_format !=
|
|
T_ATM_ABSENT) {
|
|
return(EINVAL);
|
|
}
|
|
break;
|
|
|
|
case T_ATM_E164_ADDR:
|
|
/*
|
|
* Check signalling state
|
|
*/
|
|
pvc = 0;
|
|
pvp = NULL;
|
|
if (usp->us_state != UNISIG_ACTIVE) {
|
|
return(ENETDOWN);
|
|
}
|
|
|
|
/*
|
|
* Check destination address format
|
|
*/
|
|
if (cvp->cvc_attr.called.subaddr.address_format !=
|
|
T_ATM_ENDSYS_ADDR &&
|
|
cvp->cvc_attr.called.subaddr.address_format !=
|
|
T_ATM_ABSENT) {
|
|
return(EINVAL);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return(EPROTONOSUPPORT);
|
|
}
|
|
|
|
/*
|
|
* Check that this is for the same interface UNISIG uses
|
|
*/
|
|
if (!cvp->cvc_attr.nif ||
|
|
cvp->cvc_attr.nif->nif_pif != usp->us_pif) {
|
|
return(EINVAL);
|
|
}
|
|
|
|
/*
|
|
* Allocate control block for VCC
|
|
*/
|
|
uvp = (struct unisig_vccb *)atm_allocate(&unisig_vcpool);
|
|
if (uvp == NULL) {
|
|
return(ENOMEM);
|
|
}
|
|
|
|
/*
|
|
* Fill in VCCB
|
|
*/
|
|
if (pvc) {
|
|
uvp->uv_type = VCC_PVC | VCC_IN | VCC_OUT;
|
|
uvp->uv_vpi = ATM_PVC_GET_VPI(pvp);
|
|
uvp->uv_vci = ATM_PVC_GET_VCI(pvp);
|
|
uvp->uv_sstate = (usp->us_state == UNISIG_ACTIVE ?
|
|
UNI_PVC_ACTIVE : UNI_PVC_ACT_DOWN);
|
|
uvp->uv_ustate = VCCU_OPEN;
|
|
} else {
|
|
uvp->uv_type = VCC_SVC | VCC_IN | VCC_OUT;
|
|
uvp->uv_sstate = UNI_NULL;
|
|
uvp->uv_ustate = VCCU_POPEN;
|
|
}
|
|
uvp->uv_proto = usp->us_pif->pif_sigmgr->sm_proto;
|
|
uvp->uv_pif = usp->us_pif;
|
|
uvp->uv_nif = cvp->cvc_attr.nif;
|
|
uvp->uv_connvc = cvp;
|
|
uvp->uv_tstamp = time_second;
|
|
|
|
/*
|
|
* Put VCCB on UNISIG queue
|
|
*/
|
|
ENQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
|
|
|
|
/*
|
|
* Call the VC state machine if this is an SVC
|
|
*/
|
|
if (!pvc) {
|
|
err = unisig_vc_state(usp, uvp, UNI_VC_SETUP_CALL,
|
|
(struct unisig_msg *) 0);
|
|
if (err) {
|
|
/*
|
|
* On error, delete the VCCB
|
|
*/
|
|
DEQUEUE(uvp, struct unisig_vccb, uv_sigelem,
|
|
usp->us_vccq);
|
|
atm_free((caddr_t)uvp);
|
|
return(err);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Link VCCB to VCC connection block
|
|
*/
|
|
cvp->cvc_vcc = (struct vccb *) uvp;
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Close a UNISIG VCC
|
|
*
|
|
* Called when a user wants to close a VCC. This function will clean
|
|
* up the VCCB and, for an SVC, send a close request.
|
|
*
|
|
* Must be called at splnet.
|
|
*
|
|
* Arguments:
|
|
* usp pointer to UNISIG protocol instance
|
|
* uvp pointer to VCCB for the VCC to be closed
|
|
*
|
|
* Returns:
|
|
* 0 VCC is now closed
|
|
* errno error encountered
|
|
*/
|
|
int
|
|
unisig_close_vcc(usp, uvp)
|
|
struct unisig *usp;
|
|
struct unisig_vccb *uvp;
|
|
{
|
|
int err = 0;
|
|
|
|
ATM_DEBUG2("unisig_close_vcc: uvp=%p, state=%d\n", uvp,
|
|
uvp->uv_sstate);
|
|
|
|
/*
|
|
* Check that this is for the same interface UNISIG uses
|
|
*/
|
|
if (uvp->uv_pif != usp->us_pif) {
|
|
return (EINVAL);
|
|
}
|
|
|
|
/*
|
|
* Mark the close time.
|
|
*/
|
|
uvp->uv_tstamp = time_second;
|
|
|
|
/*
|
|
* Process based on the connection type
|
|
*/
|
|
if (uvp->uv_type & VCC_PVC) {
|
|
uvp->uv_sstate = UNI_FREE;
|
|
uvp->uv_ustate = VCCU_CLOSED;
|
|
} else if (uvp->uv_type & VCC_SVC) {
|
|
/*
|
|
* Call the VC state machine
|
|
*/
|
|
uvp->uv_ustate = VCCU_CLOSED;
|
|
err = unisig_vc_state(usp, uvp, UNI_VC_RELEASE_CALL,
|
|
(struct unisig_msg *) 0);
|
|
}
|
|
|
|
/*
|
|
* Wait for user to free resources
|
|
*/
|
|
return(err);
|
|
}
|
|
|
|
|
|
/*
|
|
* Clear a UNISIG VCC
|
|
*
|
|
* Called to internally clear a VCC. No external protocol is
|
|
* initiated, the VCC is just closed and the owner is notified.
|
|
*
|
|
* Must be called at splnet.
|
|
*
|
|
* Arguments:
|
|
* usp pointer to UNISIG protocol instance
|
|
* uvp pointer to VCCB for the VCC to be closed
|
|
* cause cause code giving the reason for the close
|
|
*
|
|
* Returns:
|
|
* 0 VCC is closed
|
|
* errno error encountered
|
|
*/
|
|
int
|
|
unisig_clear_vcc(usp, uvp, cause)
|
|
struct unisig *usp;
|
|
struct unisig_vccb *uvp;
|
|
int cause;
|
|
{
|
|
u_char outstate;
|
|
|
|
ATM_DEBUG3("unisig_clear_vcc: uvp=%p, state=%d, cause=%d\n",
|
|
uvp, uvp->uv_sstate, cause);
|
|
|
|
/*
|
|
* Check that this is for the same interface UNISIG uses
|
|
*/
|
|
if (uvp->uv_pif != usp->us_pif) {
|
|
return (EINVAL);
|
|
}
|
|
|
|
/*
|
|
* Kill any possible timer
|
|
*/
|
|
UNISIG_VC_CANCEL((struct vccb *) uvp);
|
|
|
|
/*
|
|
* Mark the close time.
|
|
*/
|
|
uvp->uv_tstamp = time_second;
|
|
|
|
/*
|
|
* Close the VCC and notify the user
|
|
*/
|
|
outstate = uvp->uv_sstate;
|
|
uvp->uv_sstate = UNI_FREE;
|
|
uvp->uv_ustate = VCCU_CLOSED;
|
|
if (outstate == UNI_ACTIVE ||
|
|
outstate == UNI_CALL_INITIATED ||
|
|
outstate == UNI_CALL_OUT_PROC ||
|
|
outstate == UNI_CONNECT_REQUEST ||
|
|
outstate == UNI_RELEASE_REQUEST ||
|
|
outstate == UNI_RELEASE_IND ||
|
|
outstate == UNI_SSCF_RECOV ||
|
|
outstate == UNI_PVC_ACT_DOWN ||
|
|
outstate == UNI_PVC_ACTIVE) {
|
|
unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr, cause);
|
|
atm_cm_cleared(uvp->uv_connvc);
|
|
}
|
|
|
|
/*
|
|
* Wait for user to free resources
|
|
*/
|
|
return(0);
|
|
}
|
|
|
|
|
|
#ifdef NOTDEF
|
|
/*
|
|
* Reset the switch state
|
|
*
|
|
* Arguments:
|
|
* usp pointer to UNISIG protocol instance
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
unisig_switch_reset(usp, cause)
|
|
struct unisig *usp;
|
|
int cause;
|
|
{
|
|
int s;
|
|
struct unisig_vccb *uvp, *vnext;
|
|
|
|
ATM_DEBUG2("unisig_switch_reset: usp=%p, cause=%d\n",
|
|
usp, cause);
|
|
|
|
/*
|
|
* Terminate all of our VCCs
|
|
*/
|
|
s = splnet();
|
|
for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
|
|
uvp = vnext) {
|
|
vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
|
|
|
|
if (uvp->uv_type & VCC_SVC) {
|
|
/*
|
|
* Close the SVC and notify the owner
|
|
*/
|
|
(void)unisig_clear_vcc(usp, uvp,
|
|
T_ATM_CAUSE_NORMAL_CALL_CLEARING);
|
|
} else if (uvp->uv_type & VCC_PVC) {
|
|
/*
|
|
* Notify PVC owner of the state change
|
|
*/
|
|
switch(cause) {
|
|
case UNI_DOWN:
|
|
uvp->uv_sstate = UNI_PVC_ACT_DOWN;
|
|
break;
|
|
case UNI_UP:
|
|
uvp->uv_sstate = UNI_PVC_ACTIVE;
|
|
break;
|
|
}
|
|
atm_cm_cleared(uvp->uv_connvc, cause);
|
|
} else {
|
|
log(LOG_ERR, "unisig: invalid VCC type: vccb=%p, type=%d\n",
|
|
uvp, uvp->uv_type);
|
|
}
|
|
}
|
|
(void) splx(s);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Copy connection parameters from UNI 3.0 message IEs into
|
|
* an attribute block
|
|
*
|
|
* Arguments:
|
|
* usp pointer to UNISIG protocol instance
|
|
* msg pointer to the SETUP message
|
|
* ap pointer to the attribute block
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
unisig_save_attrs(usp, msg, ap)
|
|
struct unisig *usp;
|
|
struct unisig_msg *msg;
|
|
Atm_attributes *ap;
|
|
{
|
|
/*
|
|
* Sanity check
|
|
*/
|
|
if (!msg || !ap)
|
|
return;
|
|
|
|
/*
|
|
* Save the AAL parameters (AAL 3/4 and AAL 5 only)
|
|
*/
|
|
if (msg->msg_ie_aalp) {
|
|
struct ie_generic *aalp = msg->msg_ie_aalp;
|
|
|
|
switch(msg->msg_ie_aalp->ie_aalp_aal_type) {
|
|
case UNI_IE_AALP_AT_AAL3:
|
|
ap->aal.tag = T_ATM_PRESENT;
|
|
ap->aal.type =
|
|
msg->msg_ie_aalp->ie_aalp_aal_type;
|
|
ap->aal.v.aal4.forward_max_SDU_size =
|
|
msg->msg_ie_aalp->ie_aalp_4_fwd_max_sdu;
|
|
ap->aal.v.aal4.backward_max_SDU_size =
|
|
msg->msg_ie_aalp->ie_aalp_4_bkwd_max_sdu;
|
|
ap->aal.v.aal4.SSCS_type =
|
|
msg->msg_ie_aalp->ie_aalp_4_sscs_type;
|
|
if (aalp->ie_aalp_4_mid_range == T_ATM_ABSENT) {
|
|
ap->aal.v.aal4.mid_low = T_ATM_ABSENT;
|
|
ap->aal.v.aal4.mid_high = T_ATM_ABSENT;
|
|
} else {
|
|
if (usp->us_proto == ATM_SIG_UNI30) {
|
|
ap->aal.v.aal4.mid_low = 0;
|
|
ap->aal.v.aal4.mid_high =
|
|
aalp->ie_aalp_4_mid_range
|
|
& UNI_IE_AALP_A3_R_MASK;
|
|
} else {
|
|
ap->aal.v.aal4.mid_low =
|
|
(aalp->ie_aalp_4_mid_range >>
|
|
UNI_IE_AALP_A3_R_SHIFT)
|
|
& UNI_IE_AALP_A3_R_MASK;
|
|
ap->aal.v.aal4.mid_high =
|
|
aalp->ie_aalp_4_mid_range
|
|
& UNI_IE_AALP_A3_R_MASK;
|
|
}
|
|
}
|
|
break;
|
|
case UNI_IE_AALP_AT_AAL5:
|
|
ap->aal.tag = T_ATM_PRESENT;
|
|
ap->aal.type =
|
|
msg->msg_ie_aalp->ie_aalp_aal_type;
|
|
ap->aal.v.aal5.forward_max_SDU_size =
|
|
msg->msg_ie_aalp->ie_aalp_5_fwd_max_sdu;
|
|
ap->aal.v.aal5.backward_max_SDU_size =
|
|
msg->msg_ie_aalp->ie_aalp_5_bkwd_max_sdu;
|
|
ap->aal.v.aal5.SSCS_type =
|
|
msg->msg_ie_aalp->ie_aalp_5_sscs_type;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Save traffic descriptor attributes
|
|
*/
|
|
if (msg->msg_ie_clrt) {
|
|
ap->traffic.tag = T_ATM_PRESENT;
|
|
ap->traffic.v.forward.PCR_high_priority =
|
|
msg->msg_ie_clrt->ie_clrt_fwd_peak;
|
|
ap->traffic.v.forward.PCR_all_traffic =
|
|
msg->msg_ie_clrt->ie_clrt_fwd_peak_01;
|
|
ap->traffic.v.forward.SCR_high_priority =
|
|
msg->msg_ie_clrt->ie_clrt_fwd_sust;
|
|
ap->traffic.v.forward.SCR_all_traffic =
|
|
msg->msg_ie_clrt->ie_clrt_fwd_sust_01;
|
|
ap->traffic.v.forward.MBS_high_priority =
|
|
msg->msg_ie_clrt->ie_clrt_fwd_burst;
|
|
ap->traffic.v.forward.MBS_all_traffic =
|
|
msg->msg_ie_clrt->ie_clrt_fwd_burst_01;
|
|
ap->traffic.v.backward.PCR_high_priority =
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_peak;
|
|
ap->traffic.v.backward.PCR_all_traffic =
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_peak_01;
|
|
ap->traffic.v.backward.SCR_high_priority =
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_sust;
|
|
ap->traffic.v.backward.SCR_all_traffic =
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_sust_01;
|
|
ap->traffic.v.backward.MBS_high_priority =
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_burst;
|
|
ap->traffic.v.backward.MBS_all_traffic =
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_burst_01;
|
|
ap->traffic.v.best_effort =
|
|
msg->msg_ie_clrt->ie_clrt_best_effort;
|
|
if (msg->msg_ie_clrt->ie_clrt_tm_options ==
|
|
T_ATM_ABSENT) {
|
|
ap->traffic.v.forward.tagging = T_NO;
|
|
ap->traffic.v.backward.tagging = T_NO;
|
|
} else {
|
|
ap->traffic.v.forward.tagging =
|
|
(msg->msg_ie_clrt->ie_clrt_tm_options &
|
|
UNI_IE_CLRT_TM_FWD_TAG) != 0;
|
|
ap->traffic.v.backward.tagging =
|
|
(msg->msg_ie_clrt->ie_clrt_tm_options &
|
|
UNI_IE_CLRT_TM_BKWD_TAG) != 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Save broadband bearer attributes
|
|
*/
|
|
if (msg->msg_ie_bbcp) {
|
|
ap->bearer.tag = T_ATM_PRESENT;
|
|
ap->bearer.v.bearer_class =
|
|
msg->msg_ie_bbcp->ie_bbcp_bearer_class;
|
|
ap->bearer.v.traffic_type =
|
|
msg->msg_ie_bbcp->ie_bbcp_traffic_type;
|
|
ap->bearer.v.timing_requirements =
|
|
msg->msg_ie_bbcp->ie_bbcp_timing_req;
|
|
ap->bearer.v.clipping_susceptibility =
|
|
msg->msg_ie_bbcp->ie_bbcp_clipping;
|
|
ap->bearer.v.connection_configuration =
|
|
msg->msg_ie_bbcp->ie_bbcp_conn_config;
|
|
}
|
|
|
|
/*
|
|
* Save broadband high layer attributes
|
|
*/
|
|
if (msg->msg_ie_bhli) {
|
|
ap->bhli.tag = T_ATM_PRESENT;
|
|
ap->bhli.v.ID_type = msg->msg_ie_bhli->ie_bhli_type;
|
|
switch(ap->bhli.v.ID_type) {
|
|
case T_ATM_ISO_APP_ID:
|
|
KM_COPY(msg->msg_ie_bhli->ie_bhli_info,
|
|
ap->bhli.v.ID.ISO_ID,
|
|
sizeof(ap->bhli.v.ID.ISO_ID));
|
|
break;
|
|
case T_ATM_USER_APP_ID:
|
|
KM_COPY(msg->msg_ie_bhli->ie_bhli_info,
|
|
ap->bhli.v.ID.user_defined_ID,
|
|
sizeof(ap->bhli.v.ID.user_defined_ID));
|
|
break;
|
|
case T_ATM_VENDOR_APP_ID:
|
|
KM_COPY(msg->msg_ie_bhli->ie_bhli_info,
|
|
ap->bhli.v.ID.vendor_ID.OUI,
|
|
sizeof(ap->bhli.v.ID.vendor_ID.OUI));
|
|
KM_COPY(&msg->msg_ie_bhli->ie_bhli_info[sizeof(ap->bhli.v.ID.vendor_ID.OUI)-1],
|
|
ap->bhli.v.ID.vendor_ID.app_ID,
|
|
sizeof(ap->bhli.v.ID.vendor_ID.app_ID));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Save Broadband low layer, user layer 2 and 3 attributes
|
|
*/
|
|
if (msg->msg_ie_blli) {
|
|
/*
|
|
* Layer 2 parameters
|
|
*/
|
|
switch(msg->msg_ie_blli->ie_blli_l2_id) {
|
|
case UNI_IE_BLLI_L2P_ISO1745:
|
|
case UNI_IE_BLLI_L2P_Q921:
|
|
case UNI_IE_BLLI_L2P_X25L:
|
|
case UNI_IE_BLLI_L2P_X25M:
|
|
case UNI_IE_BLLI_L2P_LAPB:
|
|
case UNI_IE_BLLI_L2P_HDLC1:
|
|
case UNI_IE_BLLI_L2P_HDLC2:
|
|
case UNI_IE_BLLI_L2P_HDLC3:
|
|
case UNI_IE_BLLI_L2P_LLC:
|
|
case UNI_IE_BLLI_L2P_X75:
|
|
case UNI_IE_BLLI_L2P_Q922:
|
|
case UNI_IE_BLLI_L2P_ISO7776:
|
|
ap->blli.tag_l2 = T_ATM_PRESENT;
|
|
ap->blli.v.layer_2_protocol.ID_type =
|
|
T_ATM_SIMPLE_ID;
|
|
ap->blli.v.layer_2_protocol.ID.simple_ID =
|
|
msg->msg_ie_blli->ie_blli_l2_id;
|
|
break;
|
|
case UNI_IE_BLLI_L2P_USER:
|
|
ap->blli.tag_l2 = T_ATM_PRESENT;
|
|
ap->blli.v.layer_2_protocol.ID_type =
|
|
T_ATM_USER_ID;
|
|
ap->blli.v.layer_2_protocol.ID.user_defined_ID =
|
|
msg->msg_ie_blli->ie_blli_l2_user_proto;
|
|
break;
|
|
default:
|
|
ap->blli.tag_l2 = T_ATM_ABSENT;
|
|
}
|
|
if (ap->blli.tag_l2 == T_ATM_PRESENT) {
|
|
ap->blli.v.layer_2_protocol.mode =
|
|
msg->msg_ie_blli->ie_blli_l2_mode;
|
|
ap->blli.v.layer_2_protocol.window_size =
|
|
msg->msg_ie_blli->ie_blli_l2_window;
|
|
}
|
|
|
|
/*
|
|
* Layer 3 parameters
|
|
*/
|
|
switch(msg->msg_ie_blli->ie_blli_l3_id) {
|
|
case UNI_IE_BLLI_L3P_X25:
|
|
case UNI_IE_BLLI_L3P_ISO8208:
|
|
case UNI_IE_BLLI_L3P_ISO8878:
|
|
case UNI_IE_BLLI_L3P_ISO8473:
|
|
case UNI_IE_BLLI_L3P_T70:
|
|
ap->blli.tag_l3 = T_ATM_PRESENT;
|
|
ap->blli.v.layer_3_protocol.ID_type =
|
|
T_ATM_SIMPLE_ID;
|
|
ap->blli.v.layer_3_protocol.ID.simple_ID =
|
|
msg->msg_ie_blli->ie_blli_l3_id;
|
|
break;
|
|
case UNI_IE_BLLI_L3P_ISO9577:
|
|
ap->blli.tag_l3 = T_ATM_PRESENT;
|
|
ap->blli.v.layer_3_protocol.ID_type =
|
|
T_ATM_SIMPLE_ID;
|
|
ap->blli.v.layer_3_protocol.ID.simple_ID =
|
|
msg->msg_ie_blli->ie_blli_l3_id;
|
|
if (msg->msg_ie_blli->ie_blli_l3_ipi ==
|
|
UNI_IE_BLLI_L3IPI_SNAP) {
|
|
KM_COPY(msg->msg_ie_blli->ie_blli_l3_oui,
|
|
ap->blli.v.layer_3_protocol.ID.SNAP_ID.OUI,
|
|
sizeof(ap->blli.v.layer_3_protocol.ID.SNAP_ID.OUI));
|
|
KM_COPY(msg->msg_ie_blli->ie_blli_l3_pid,
|
|
ap->blli.v.layer_3_protocol.ID.SNAP_ID.PID,
|
|
sizeof(ap->blli.v.layer_3_protocol.ID.SNAP_ID.PID));
|
|
} else {
|
|
ap->blli.v.layer_3_protocol.ID.IPI_ID =
|
|
msg->msg_ie_blli->ie_blli_l3_ipi;
|
|
}
|
|
break;
|
|
case UNI_IE_BLLI_L3P_USER:
|
|
ap->blli.tag_l3 = T_ATM_PRESENT;
|
|
ap->blli.v.layer_3_protocol.ID_type =
|
|
T_ATM_USER_ID;
|
|
ap->blli.v.layer_3_protocol.ID.user_defined_ID =
|
|
msg->msg_ie_blli->ie_blli_l3_user_proto;
|
|
break;
|
|
default:
|
|
ap->blli.tag_l3 = T_ATM_ABSENT;
|
|
}
|
|
if (ap->blli.tag_l3 == T_ATM_PRESENT) {
|
|
ap->blli.v.layer_3_protocol.mode =
|
|
msg->msg_ie_blli->ie_blli_l3_mode;
|
|
ap->blli.v.layer_3_protocol.packet_size =
|
|
msg->msg_ie_blli->ie_blli_l3_packet_size;
|
|
ap->blli.v.layer_3_protocol.window_size =
|
|
msg->msg_ie_blli->ie_blli_l3_window;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Save the called party address and subaddress
|
|
*/
|
|
if (msg->msg_ie_cdad) {
|
|
ap->called.tag = T_ATM_PRESENT;
|
|
ATM_ADDR_COPY(&msg->msg_ie_cdad->ie_cdad_addr,
|
|
&ap->called.addr);
|
|
ap->called.subaddr.address_format = T_ATM_ABSENT;
|
|
ap->called.subaddr.address_length = 0;
|
|
}
|
|
if (msg->msg_ie_cdsa) {
|
|
ATM_ADDR_COPY(&msg->msg_ie_cdsa->ie_cdsa_addr,
|
|
&ap->called.subaddr);
|
|
}
|
|
|
|
/*
|
|
* Save the calling party address and subaddress
|
|
*/
|
|
if (msg->msg_ie_cgad) {
|
|
ap->calling.tag = T_ATM_PRESENT;
|
|
ATM_ADDR_COPY(&msg->msg_ie_cgad->ie_cgad_addr,
|
|
&ap->calling.addr);
|
|
ap->calling.subaddr.address_format = T_ATM_ABSENT;
|
|
ap->calling.subaddr.address_length = 0;
|
|
}
|
|
|
|
if (msg->msg_ie_cgsa) {
|
|
ATM_ADDR_COPY(&msg->msg_ie_cgsa->ie_cgsa_addr,
|
|
&ap->calling.subaddr);
|
|
}
|
|
|
|
/*
|
|
* Save quality of service attributes
|
|
*/
|
|
if (msg->msg_ie_qosp) {
|
|
ap->qos.tag = T_ATM_PRESENT;
|
|
ap->qos.v.coding_standard = msg->msg_ie_qosp->ie_coding;
|
|
ap->qos.v.forward.qos_class = msg->msg_ie_qosp->ie_qosp_fwd_class;
|
|
ap->qos.v.forward.qos_class =
|
|
msg->msg_ie_qosp->ie_qosp_bkwd_class;
|
|
}
|
|
|
|
/*
|
|
* Save transit network attributes
|
|
*/
|
|
if (msg->msg_ie_trnt) {
|
|
ap->transit.tag = T_ATM_PRESENT;
|
|
ap->transit.v.length =
|
|
MIN(msg->msg_ie_trnt->ie_trnt_id_len,
|
|
sizeof(ap->transit.v.network_id));
|
|
KM_COPY(msg->msg_ie_trnt->ie_trnt_id,
|
|
ap->transit.v.network_id,
|
|
ap->transit.v.length);
|
|
}
|
|
|
|
/*
|
|
* Save cause code
|
|
*/
|
|
if (msg->msg_ie_caus) {
|
|
ap->cause.tag = T_ATM_PRESENT;
|
|
ap->cause.v.coding_standard =
|
|
msg->msg_ie_caus->ie_coding;
|
|
ap->cause.v.location =
|
|
msg->msg_ie_caus->ie_caus_loc;
|
|
ap->cause.v.cause_value =
|
|
msg->msg_ie_caus->ie_caus_cause;
|
|
KM_ZERO(ap->cause.v.diagnostics,
|
|
sizeof(ap->cause.v.diagnostics));
|
|
#ifdef NOTDEF
|
|
KM_COPY(msg->msg_ie_caus->ie_caus_diagnostic,
|
|
ap->transit.v.diagnostics,
|
|
MIN(sizeof(ap->transit.v.diagnostics),
|
|
msg->msg_ie_caus->ie_caus_diag_len));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Copy connection parameters from an attribute block into
|
|
* UNI 3.0 message IEs
|
|
*
|
|
* Arguments:
|
|
* usp pointer to UNISIG protocol instance
|
|
* msg pointer to the SETUP message
|
|
* ap pointer to the attribute block
|
|
*
|
|
* Returns:
|
|
* 0 everything OK
|
|
* else error encountered
|
|
*
|
|
*/
|
|
int
|
|
unisig_set_attrs(usp, msg, ap)
|
|
struct unisig *usp;
|
|
struct unisig_msg *msg;
|
|
Atm_attributes *ap;
|
|
{
|
|
int err = 0;
|
|
|
|
/*
|
|
* Sanity check
|
|
*/
|
|
if (!msg || !ap)
|
|
return(EINVAL);
|
|
|
|
/*
|
|
* Set the AAL parameters (AAL 3/4 and AAL 5 only)
|
|
*/
|
|
if (ap->aal.tag == T_ATM_PRESENT) {
|
|
if (!msg->msg_ie_aalp) {
|
|
msg->msg_ie_aalp = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_aalp == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_aalp_absent,
|
|
&msg->msg_ie_aalp->ie_u.ie_aalp,
|
|
sizeof(ie_aalp_absent));
|
|
msg->msg_ie_aalp->ie_ident = UNI_IE_AALP;
|
|
msg->msg_ie_aalp->ie_aalp_aal_type = ap->aal.type;
|
|
switch(ap->aal.type) {
|
|
case ATM_AAL3_4:
|
|
msg->msg_ie_aalp->ie_aalp_4_fwd_max_sdu =
|
|
ap->aal.v.aal4.forward_max_SDU_size;
|
|
msg->msg_ie_aalp->ie_aalp_4_bkwd_max_sdu =
|
|
ap->aal.v.aal4.backward_max_SDU_size;
|
|
msg->msg_ie_aalp->ie_aalp_4_mode = UNI_IE_AALP_A5_M_MSG;
|
|
msg->msg_ie_aalp->ie_aalp_4_sscs_type =
|
|
ap->aal.v.aal4.SSCS_type;
|
|
if (ap->aal.v.aal4.mid_low == T_ATM_ABSENT) {
|
|
msg->msg_ie_aalp->ie_aalp_4_mid_range =
|
|
T_ATM_ABSENT;
|
|
} else {
|
|
if (usp->us_proto == ATM_SIG_UNI30) {
|
|
msg->msg_ie_aalp->ie_aalp_4_mid_range =
|
|
ap->aal.v.aal4.mid_high &
|
|
UNI_IE_AALP_A3_R_MASK;
|
|
} else {
|
|
msg->msg_ie_aalp->ie_aalp_4_mid_range =
|
|
((ap->aal.v.aal4.mid_low &
|
|
UNI_IE_AALP_A3_R_MASK)
|
|
<< UNI_IE_AALP_A3_R_SHIFT)
|
|
|
|
|
(ap->aal.v.aal4.mid_high &
|
|
UNI_IE_AALP_A3_R_MASK);
|
|
}
|
|
}
|
|
break;
|
|
case ATM_AAL5:
|
|
msg->msg_ie_aalp->ie_aalp_5_fwd_max_sdu =
|
|
ap->aal.v.aal5.forward_max_SDU_size;
|
|
msg->msg_ie_aalp->ie_aalp_5_bkwd_max_sdu =
|
|
ap->aal.v.aal5.backward_max_SDU_size;
|
|
msg->msg_ie_aalp->ie_aalp_5_mode =
|
|
UNI_IE_AALP_A5_M_MSG;
|
|
msg->msg_ie_aalp->ie_aalp_5_sscs_type =
|
|
ap->aal.v.aal5.SSCS_type;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set traffic descriptor attributes
|
|
*/
|
|
if (ap->traffic.tag == T_ATM_PRESENT) {
|
|
if (!msg->msg_ie_clrt) {
|
|
msg->msg_ie_clrt = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_clrt == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_clrt_absent,
|
|
&msg->msg_ie_clrt->ie_u.ie_clrt,
|
|
sizeof(ie_clrt_absent));
|
|
msg->msg_ie_clrt->ie_ident = UNI_IE_CLRT;
|
|
msg->msg_ie_clrt->ie_clrt_fwd_peak =
|
|
ap->traffic.v.forward.PCR_high_priority;
|
|
msg->msg_ie_clrt->ie_clrt_fwd_peak_01 =
|
|
ap->traffic.v.forward.PCR_all_traffic;
|
|
msg->msg_ie_clrt->ie_clrt_fwd_sust =
|
|
ap->traffic.v.forward.SCR_high_priority;
|
|
msg->msg_ie_clrt->ie_clrt_fwd_sust_01 =
|
|
ap->traffic.v.forward.SCR_all_traffic;
|
|
msg->msg_ie_clrt->ie_clrt_fwd_burst =
|
|
ap->traffic.v.forward.MBS_high_priority;
|
|
msg->msg_ie_clrt->ie_clrt_fwd_burst_01 =
|
|
ap->traffic.v.forward.MBS_all_traffic;
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_peak =
|
|
ap->traffic.v.backward.PCR_high_priority;
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_peak_01 =
|
|
ap->traffic.v.backward.PCR_all_traffic;
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_sust =
|
|
ap->traffic.v.backward.SCR_high_priority;
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_sust_01 =
|
|
ap->traffic.v.backward.SCR_all_traffic;
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_burst =
|
|
ap->traffic.v.backward.MBS_high_priority;
|
|
msg->msg_ie_clrt->ie_clrt_bkwd_burst_01 =
|
|
ap->traffic.v.backward.MBS_all_traffic;
|
|
msg->msg_ie_clrt->ie_clrt_best_effort =
|
|
ap->traffic.v.best_effort;
|
|
msg->msg_ie_clrt->ie_clrt_tm_options = 0;
|
|
if (ap->traffic.v.forward.tagging) {
|
|
msg->msg_ie_clrt->ie_clrt_tm_options |=
|
|
UNI_IE_CLRT_TM_FWD_TAG;
|
|
}
|
|
if (ap->traffic.v.backward.tagging) {
|
|
msg->msg_ie_clrt->ie_clrt_tm_options |=
|
|
UNI_IE_CLRT_TM_BKWD_TAG;
|
|
}
|
|
if (msg->msg_ie_clrt->ie_clrt_tm_options == 0) {
|
|
msg->msg_ie_clrt->ie_clrt_tm_options =
|
|
T_ATM_ABSENT;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set broadband bearer attributes
|
|
*/
|
|
if (ap->bearer.tag == T_ATM_PRESENT) {
|
|
if (!msg->msg_ie_bbcp) {
|
|
msg->msg_ie_bbcp = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_bbcp == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_bbcp_absent,
|
|
&msg->msg_ie_bbcp->ie_u.ie_bbcp,
|
|
sizeof(ie_bbcp_absent));
|
|
msg->msg_ie_bbcp->ie_ident = UNI_IE_BBCP;
|
|
msg->msg_ie_bbcp->ie_bbcp_bearer_class =
|
|
ap->bearer.v.bearer_class;
|
|
msg->msg_ie_bbcp->ie_bbcp_traffic_type =
|
|
ap->bearer.v.traffic_type;
|
|
msg->msg_ie_bbcp->ie_bbcp_timing_req =
|
|
ap->bearer.v.timing_requirements;
|
|
msg->msg_ie_bbcp->ie_bbcp_clipping =
|
|
ap->bearer.v.clipping_susceptibility;
|
|
msg->msg_ie_bbcp->ie_bbcp_conn_config =
|
|
ap->bearer.v.connection_configuration;
|
|
}
|
|
|
|
/*
|
|
* Set broadband high layer attributes
|
|
*/
|
|
if (ap->bhli.tag == T_ATM_PRESENT) {
|
|
if (!msg->msg_ie_bhli) {
|
|
msg->msg_ie_bhli = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_bhli == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_bhli_absent,
|
|
&msg->msg_ie_bhli->ie_u.ie_bhli,
|
|
sizeof(ie_bhli_absent));
|
|
msg->msg_ie_bhli->ie_ident = UNI_IE_BHLI;
|
|
msg->msg_ie_bhli->ie_bhli_type = ap->bhli.v.ID_type;
|
|
switch (ap->bhli.v.ID_type) {
|
|
case T_ATM_ISO_APP_ID:
|
|
KM_COPY(ap->bhli.v.ID.ISO_ID,
|
|
msg->msg_ie_bhli->ie_bhli_info,
|
|
sizeof(ap->bhli.v.ID.ISO_ID));
|
|
break;
|
|
case T_ATM_USER_APP_ID:
|
|
KM_COPY(ap->bhli.v.ID.user_defined_ID,
|
|
msg->msg_ie_bhli->ie_bhli_info,
|
|
sizeof(ap->bhli.v.ID.user_defined_ID));
|
|
break;
|
|
case T_ATM_VENDOR_APP_ID:
|
|
KM_COPY(ap->bhli.v.ID.vendor_ID.OUI,
|
|
msg->msg_ie_bhli->ie_bhli_info,
|
|
sizeof(ap->bhli.v.ID.vendor_ID.OUI));
|
|
KM_COPY(ap->bhli.v.ID.vendor_ID.app_ID,
|
|
&msg->msg_ie_bhli->ie_bhli_info[sizeof(ap->bhli.v.ID.vendor_ID.OUI)-1],
|
|
sizeof(ap->bhli.v.ID.vendor_ID.app_ID));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set Broadband low layer, user layer 2 and 3 attributes
|
|
*/
|
|
if (ap->blli.tag_l2 == T_ATM_PRESENT ||
|
|
ap->blli.tag_l3 == T_ATM_PRESENT) {
|
|
if (!msg->msg_ie_blli) {
|
|
msg->msg_ie_blli = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_blli == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_blli_absent,
|
|
&msg->msg_ie_blli->ie_u.ie_blli,
|
|
sizeof(ie_blli_absent));
|
|
msg->msg_ie_blli->ie_ident = UNI_IE_BLLI;
|
|
|
|
if (ap->blli.tag_l2 == T_ATM_PRESENT) {
|
|
switch(ap->blli.v.layer_2_protocol.ID_type) {
|
|
case T_ATM_SIMPLE_ID:
|
|
msg->msg_ie_blli->ie_blli_l2_id =
|
|
ap->blli.v.layer_2_protocol.ID.simple_ID;
|
|
break;
|
|
case T_ATM_USER_ID:
|
|
msg->msg_ie_blli->ie_blli_l2_id =
|
|
UNI_IE_BLLI_L2P_USER;
|
|
msg->msg_ie_blli->ie_blli_l2_user_proto =
|
|
ap->blli.v.layer_2_protocol.ID.user_defined_ID;
|
|
break;
|
|
}
|
|
if (ap->blli.v.layer_2_protocol.ID_type !=
|
|
T_ATM_ABSENT) {
|
|
msg->msg_ie_blli->ie_blli_l2_mode =
|
|
ap->blli.v.layer_2_protocol.mode;
|
|
msg->msg_ie_blli->ie_blli_l2_window =
|
|
ap->blli.v.layer_2_protocol.window_size;
|
|
}
|
|
}
|
|
|
|
if (ap->blli.tag_l3 == T_ATM_PRESENT) {
|
|
switch (ap->blli.v.layer_3_protocol.ID_type) {
|
|
case T_ATM_SIMPLE_ID:
|
|
msg->msg_ie_blli->ie_blli_l3_id =
|
|
ap->blli.v.layer_3_protocol.ID.simple_ID;
|
|
break;
|
|
|
|
case T_ATM_IPI_ID:
|
|
msg->msg_ie_blli->ie_blli_l3_id =
|
|
UNI_IE_BLLI_L3P_ISO9577;
|
|
msg->msg_ie_blli->ie_blli_l3_ipi =
|
|
ap->blli.v.layer_3_protocol.ID.IPI_ID;
|
|
break;
|
|
|
|
case T_ATM_SNAP_ID:
|
|
msg->msg_ie_blli->ie_blli_l3_id =
|
|
UNI_IE_BLLI_L3P_ISO9577;
|
|
msg->msg_ie_blli->ie_blli_l3_ipi =
|
|
UNI_IE_BLLI_L3IPI_SNAP;
|
|
KM_COPY(ap->blli.v.layer_3_protocol.ID.SNAP_ID.OUI,
|
|
msg->msg_ie_blli->ie_blli_l3_oui,
|
|
sizeof(msg->msg_ie_blli->ie_blli_l3_oui));
|
|
KM_COPY(ap->blli.v.layer_3_protocol.ID.SNAP_ID.PID,
|
|
msg->msg_ie_blli->ie_blli_l3_pid,
|
|
sizeof(msg->msg_ie_blli->ie_blli_l3_pid));
|
|
break;
|
|
|
|
case T_ATM_USER_ID:
|
|
msg->msg_ie_blli->ie_blli_l3_id =
|
|
UNI_IE_BLLI_L3P_USER;
|
|
msg->msg_ie_blli->ie_blli_l3_user_proto =
|
|
ap->blli.v.layer_3_protocol.ID.user_defined_ID;
|
|
break;
|
|
}
|
|
if (ap->blli.v.layer_3_protocol.ID_type
|
|
!= T_ATM_ABSENT) {
|
|
msg->msg_ie_blli->ie_blli_l3_mode =
|
|
ap->blli.v.layer_3_protocol.mode;
|
|
msg->msg_ie_blli->ie_blli_l3_packet_size =
|
|
ap->blli.v.layer_3_protocol.packet_size;
|
|
msg->msg_ie_blli->ie_blli_l3_window =
|
|
ap->blli.v.layer_3_protocol.window_size;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the called party address and subaddress
|
|
*/
|
|
if (ap->called.tag == T_ATM_PRESENT) {
|
|
if (!msg->msg_ie_cdad) {
|
|
msg->msg_ie_cdad = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_cdad == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_cdad_absent,
|
|
&msg->msg_ie_cdad->ie_u.ie_cdad,
|
|
sizeof(ie_cdad_absent));
|
|
msg->msg_ie_cdad->ie_ident = UNI_IE_CDAD;
|
|
ATM_ADDR_COPY(&ap->called.addr,
|
|
&msg->msg_ie_cdad->ie_cdad_addr);
|
|
|
|
if (ap->called.subaddr.address_format != T_ATM_ABSENT) {
|
|
if (!msg->msg_ie_cdsa) {
|
|
msg->msg_ie_cdsa = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_cdsa == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_cdsa_absent,
|
|
&msg->msg_ie_cdsa->ie_u.ie_cdsa,
|
|
sizeof(ie_cdsa_absent));
|
|
msg->msg_ie_cdsa->ie_ident = UNI_IE_CDSA;
|
|
ATM_ADDR_COPY(&ap->called.subaddr,
|
|
&msg->msg_ie_cdsa->ie_cdsa_addr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the calling party address and subaddress
|
|
*/
|
|
|
|
if (ap->calling.tag == T_ATM_PRESENT) {
|
|
if (!msg->msg_ie_cgad) {
|
|
msg->msg_ie_cgad = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_cgad == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_cgad_absent,
|
|
&msg->msg_ie_cgad->ie_u.ie_cgad,
|
|
sizeof(ie_cgad_absent));
|
|
msg->msg_ie_cgsa->ie_ident = UNI_IE_CGSA;
|
|
ATM_ADDR_COPY(&ap->calling.addr,
|
|
&msg->msg_ie_cgad->ie_cgad_addr);
|
|
|
|
if (ap->calling.subaddr.address_format !=
|
|
T_ATM_ABSENT) {
|
|
if (!msg->msg_ie_cgsa) {
|
|
msg->msg_ie_cgsa = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_cgsa == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_cgsa_absent,
|
|
&msg->msg_ie_cgsa->ie_u.ie_cgsa,
|
|
sizeof(ie_cgsa_absent));
|
|
msg->msg_ie_cgsa->ie_ident = UNI_IE_CGSA;
|
|
ATM_ADDR_COPY(&ap->calling.subaddr,
|
|
&msg->msg_ie_cgsa->ie_cgsa_addr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set quality of service attributes
|
|
*/
|
|
if (ap->qos.tag == T_ATM_PRESENT) {
|
|
if (!msg->msg_ie_qosp) {
|
|
msg->msg_ie_qosp = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_qosp == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_qosp_absent,
|
|
&msg->msg_ie_qosp->ie_u.ie_qosp,
|
|
sizeof(ie_qosp_absent));
|
|
msg->msg_ie_qosp->ie_ident = UNI_IE_QOSP;
|
|
if (usp->us_proto == ATM_SIG_UNI30)
|
|
msg->msg_ie_qosp->ie_coding = UNI_IE_CODE_STD;
|
|
else if ((ap->qos.v.forward.qos_class ==
|
|
T_ATM_QOS_CLASS_0) ||
|
|
(ap->qos.v.backward.qos_class ==
|
|
T_ATM_QOS_CLASS_0))
|
|
msg->msg_ie_qosp->ie_coding = UNI_IE_CODE_CCITT;
|
|
else
|
|
msg->msg_ie_qosp->ie_coding = ap->qos.v.coding_standard;
|
|
msg->msg_ie_qosp->ie_qosp_fwd_class =
|
|
ap->qos.v.forward.qos_class;
|
|
msg->msg_ie_qosp->ie_qosp_bkwd_class =
|
|
ap->qos.v.backward.qos_class;
|
|
}
|
|
|
|
/*
|
|
* Set transit network attributes
|
|
*/
|
|
if (ap->transit.tag == T_ATM_PRESENT &&
|
|
ap->transit.v.length != 0) {
|
|
if (!msg->msg_ie_trnt) {
|
|
msg->msg_ie_trnt = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_trnt == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_trnt_absent,
|
|
&msg->msg_ie_trnt->ie_u.ie_trnt,
|
|
sizeof(ie_trnt_absent));
|
|
msg->msg_ie_trnt->ie_ident = UNI_IE_TRNT;
|
|
msg->msg_ie_trnt->ie_trnt_id_type =
|
|
UNI_IE_TRNT_IDT_NATL;
|
|
msg->msg_ie_trnt->ie_trnt_id_plan =
|
|
UNI_IE_TRNT_IDP_CIC;
|
|
KM_COPY(ap->transit.v.network_id,
|
|
msg->msg_ie_trnt->ie_trnt_id,
|
|
ap->transit.v.length);
|
|
}
|
|
|
|
/*
|
|
* Set cause code
|
|
*/
|
|
if (ap->cause.tag == T_ATM_PRESENT) {
|
|
if (!msg->msg_ie_caus) {
|
|
msg->msg_ie_caus = (struct ie_generic *)
|
|
atm_allocate(&unisig_iepool);
|
|
if (msg->msg_ie_caus == NULL) {
|
|
err = ENOMEM;
|
|
goto done;
|
|
}
|
|
}
|
|
KM_COPY(&ie_caus_absent,
|
|
&msg->msg_ie_caus->ie_u.ie_caus,
|
|
sizeof(ie_caus_absent));
|
|
msg->msg_ie_caus->ie_ident = UNI_IE_CAUS;
|
|
msg->msg_ie_caus->ie_coding =
|
|
ap->cause.v.coding_standard;
|
|
msg->msg_ie_caus->ie_caus_loc =
|
|
ap->cause.v.location;
|
|
msg->msg_ie_caus->ie_caus_cause =
|
|
ap->cause.v.cause_value;
|
|
|
|
/*
|
|
* Don't copy the diagnostics from the attribute
|
|
* block, as there's no way to tell how much of
|
|
* the diagnostic field is relevant
|
|
*/
|
|
msg->msg_ie_caus->ie_caus_diag_len = 0;
|
|
}
|
|
|
|
done:
|
|
return(err);
|
|
}
|