line source
/*----------------------------------------------------------------------------
| Project : 3G PS
| Module : SM
+-----------------------------------------------------------------------------
| Copyright 2003 Texas Instruments.
| All rights reserved.
|
| This file is confidential and a trade secret of Texas
| Instruments .
| The receipt of or possession of this file does not convey
| any rights to reproduce or disclose its contents or to
| manufacture, use, or sell anything it may describe, in
| whole, or in part, without the specific written consent of
| Texas Instruments.
+-----------------------------------------------------------------------------
| Purpose: Memory allocation function definition for the SM Entity.
| For design details, see:
| 8010.908 SM Detailed Specification
+---------------------------------------------------------------------------*/
/*==== DECLARATION CONTROL =================================================*/
/*==== INCLUDES =============================================================*/
#include "sm.h"
#include "sm_tft.h"
/*==== CONSTS ===============================================================*/
/*==== TYPES ================================================================*/
/*==== LOCALS ===============================================================*/
/*==== PRIVATE FUNCTIONS ====================================================*/
/*==== PUBLIC FUNCTIONS =====================================================*/
/*
+------------------------------------------------------------------------------
| Function : sm_pfree
+------------------------------------------------------------------------------
| Description : PFREE macro replacement
|
| Parameters : data - memory to free
+------------------------------------------------------------------------------
*/
void sm_pfree(/*@only@*/ /*@null@*/ /*@out@*/ void *data)
{
if (data != NULL)
{
vsi_c_pfree((T_VOID_STRUCT **)&data FILE_LINE_MACRO);
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_mfree
+------------------------------------------------------------------------------
| Description : Wrapper for MFREE macro
|
| Parameters : data - memory to free
+------------------------------------------------------------------------------
*/
static void sm_mfree(/*@only@*/ /*@out@*/ /*@null@*/ void *data)
{
if (data != NULL) {
MFREE(data);
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_allocate_context_data
+------------------------------------------------------------------------------
| Description : Allocate an instance of SM_CONTEXT_DATA
|
| Parameters : None
+------------------------------------------------------------------------------
*/
struct T_SM_CONTEXT_DATA *sm_allocate_context_data(void)
{
struct T_SM_CONTEXT_DATA *context;
context = (struct T_SM_CONTEXT_DATA *)
M_ALLOC((U32)sizeof(struct T_SM_CONTEXT_DATA));
return context;
}
/*
+------------------------------------------------------------------------------
| Function : sm_assign_context_data_to_nsapi
+------------------------------------------------------------------------------
| Description : Assign a non-zero context data structure to an NSAPI index in
| sm_context_array.
|
| Parameters : context - Context data
| nsapi - Index at which to insert data
+------------------------------------------------------------------------------
*/
void
sm_assign_context_data_to_nsapi(/*@only@*/struct T_SM_CONTEXT_DATA *context,
int /*@alt U8@*/ nsapi)
{
TRACE_ASSERT(context != NULL);
TRACE_ASSERT(sm_data.sm_context_array[nsapi - (int)NAS_NSAPI_5] == NULL);
sm_data.sm_context_array[nsapi - (int)NAS_NSAPI_5] = context;
}
/*
+------------------------------------------------------------------------------
| Function : sm_get_context_data_from_nsapi
+------------------------------------------------------------------------------
| Description : Returns a context data structure for the given NSAPI index.
| Returns NULL, if the context is inactive.
|
| Parameters : nsapi - Index at which to fetch data
+------------------------------------------------------------------------------
*/
struct T_SM_CONTEXT_DATA *
sm_get_context_data_from_nsapi(int /*@alt U8@*/ nsapi)
{
TRACE_ASSERT((T_NAS_nsapi)nsapi >= NAS_NSAPI_5 && nsapi <= NAS_NSAPI_15);
/*lint -e{661} sm_context_array causes out of bounds access, it does not! */
return sm_data.sm_context_array[nsapi - (int)NAS_NSAPI_5];
}
/*
+------------------------------------------------------------------------------
| Function : sm_assign_context_data_to_nsapi
+------------------------------------------------------------------------------
| Description : Returns a context data structure for the given TI value.
| Returns NULL, if the context is inactive.
|
| Parameters : ti - TI value identifying the context
+------------------------------------------------------------------------------
*/
/*@null@*/struct T_SM_CONTEXT_DATA *
sm_get_context_data_from_ti(int /*@alt U8@*/ ti)
{
int index;
/* First, search sm_context_array: */
for (index = 0; index < SM_MAX_NSAPI_OFFSET; index++) {
if (sm_data.sm_context_array[index] != NULL &&
(sm_data.sm_context_array[index]->ti & SM_TI_MASK) == (ti & SM_TI_MASK))
{
return sm_data.sm_context_array[index];
}
}
/* Next, try in sm_pending_mt_array: */
for (index = 0; index < SM_MAX_NSAPI_OFFSET; index++) {
if (sm_data.sm_pending_mt_array[index] != NULL &&
sm_data.sm_pending_mt_array[index]->ti == ti)
{
return sm_data.sm_pending_mt_array[index];
}
}
/* None found: return NULL */
return NULL;
}
/*
+------------------------------------------------------------------------------
| Function : sm_free_context_data
+------------------------------------------------------------------------------
| Description : Free context data memory. Calls de-initialization functions
| in state machines.
|
| Parameters : context - Context data
+------------------------------------------------------------------------------
*/
void sm_free_context_data(/*@only@*/struct T_SM_CONTEXT_DATA *context)
{
if (context != NULL) {
sm_user_plane_control_exit (context);
sm_network_control_exit (context);
sm_context_deactivate_control_exit(context);
sm_context_control_exit (context);
TRACE_ASSERT(context->apn == NULL);
TRACE_ASSERT(context->requested_pco == NULL);
TRACE_ASSERT(context->negotiated_pco == NULL);
TRACE_ASSERT(context->requested_tft.ptr_tft_pf == NULL);
TRACE_ASSERT(context->active_tft.ptr_tft_pf == NULL);
TRACE_ASSERT(context->coded_msg == NULL);
sm_mfree(context);
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_free_context_data_by_nsapi
+------------------------------------------------------------------------------
| Description : Frees context identified by NSAPI. Uses sm_free_context_data()
|
| Parameters : nsapi - NSAPI
+------------------------------------------------------------------------------
*/
void sm_free_context_data_by_nsapi(int /*@alt U8@*/ nsapi)
{
U16 index;
TRACE_ASSERT((T_NAS_nsapi)nsapi >= NAS_NSAPI_5 && nsapi <= NAS_NSAPI_15);
index = sm_nsapi_to_index((U16)nsapi);
sm_free_context_data(sm_data.sm_context_array[index]);
sm_data.sm_context_array[index] = NULL;
}
/*
+------------------------------------------------------------------------------
| Function : sm_insert_mt_context_data
+------------------------------------------------------------------------------
| Description : Allocates and inserts context data structure in
| sm_pending_mt_array.
|
| Parameters : ti - TI value identifying context
+------------------------------------------------------------------------------
*/
/*@observer@*/ /*@null@*/ struct T_SM_CONTEXT_DATA *
sm_insert_mt_context_data(int /*@alt U8@*/ ti)
{
int index, insert_index = -1;
struct T_SM_CONTEXT_DATA *context;
for (index = 0; index < SM_MAX_NSAPI_OFFSET; index++) {
if (insert_index < 0 && sm_data.sm_pending_mt_array[index] == NULL) {
insert_index = index;
}
if (sm_data.sm_pending_mt_array[index] != NULL &&
sm_data.sm_pending_mt_array[index]->ti == ti) {
(void)TRACE_EVENT_P1("ERROR: Tried to overwrite MT context data for TI=%d!", ti);
return sm_data.sm_pending_mt_array[index];
}
}
context = sm_allocate_context_data();
if (context != NULL && insert_index >= 0) {
memset(context, 0, sizeof(struct T_SM_CONTEXT_DATA));
context->ti = (U8)ti;
sm_data.sm_pending_mt_array[insert_index] = context;
} else if (insert_index < 0) {
(void)TRACE_ERROR("ERROR: No free entries in MT context data array!");
} else {
(void)TRACE_ERROR("ERROR: Unable to allocate memory for context data array!");
}
return context;
}
/*
+------------------------------------------------------------------------------
| Function : sm_extract_mt_context_data
+------------------------------------------------------------------------------
| Description : Searches sm_pending_mt_array for the input TI. Returns the
| address of the data structure found, if any; otherwise NULL.
| If found, the entry in sm_pending_mt_array is reset to NULL.
|
| Parameters : ti - TI value identifying context
+------------------------------------------------------------------------------
*/
/*@null@*/ /*@only@*/struct T_SM_CONTEXT_DATA *
sm_extract_mt_context_data(int /*@alt U8@*/ ti)
{
int index;
for (index = 0; index < SM_MAX_NSAPI_OFFSET; index++)
{
if (sm_data.sm_pending_mt_array[index] != NULL &&
sm_data.sm_pending_mt_array[index]->ti == ti)
{
struct T_SM_CONTEXT_DATA *context;
context = sm_data.sm_pending_mt_array[index];
sm_data.sm_pending_mt_array[index] = NULL;
return context;
} /* if */
} /* for */
return NULL;
}
/*
+------------------------------------------------------------------------------
| Function : sm_free_pending_mt_context_by_index
+------------------------------------------------------------------------------
| Description : Frees context in sm_pending_mt_array indentified by index
|
| Parameters : index - index in sm_pending_mt_array[]
+------------------------------------------------------------------------------
*/
void sm_free_pending_mt_context_by_index(U16 index)
{
TRACE_ASSERT(index < (U16)SM_MAX_NSAPI_OFFSET);
/*lint -e{661} sm_context_array causes out of bounds access, it does not! */
sm_free_context_data(sm_data.sm_pending_mt_array[index]);
/*lint -e{661} sm_context_array causes out of bounds access, it does not! */
sm_data.sm_pending_mt_array[index] = NULL;
}
/*
+------------------------------------------------------------------------------
| Function : sm_linked_nsapis
+------------------------------------------------------------------------------
| Description : Returns the nsapi_set of secondary contexts linked to this
| context.
|
| Parameters : context - context data
+------------------------------------------------------------------------------
*/
U16 sm_linked_nsapis(U8 ti)
{
struct T_SM_CONTEXT_DATA *context;
int nsapi;
U16 linked_nsapis = 0;
U8 linked_ti;
context = sm_get_context_data_from_ti(ti);
TRACE_ASSERT(context != NULL);
if (context EQ NULL)
return linked_nsapis;
if (sm_is_secondary(context))
{
linked_ti = context->linked_ti;
} else {
linked_ti = ti;
}
for (nsapi = (int)NAS_NSAPI_5; nsapi < NAS_SIZE_NSAPI; nsapi++)
{
context = sm_get_context_data_from_nsapi(nsapi);
if (context != NULL && context->ti != (U8)ti && context->ti != linked_ti &&
sm_is_secondary(context) && context->linked_ti == (U8)ti)
{
linked_nsapis = sm_add_nsapi_to_nsapi_set(nsapi, linked_nsapis);
} /* if */
} /* for */
return linked_nsapis;
}
/*
+------------------------------------------------------------------------------
| Function : sm_free_coded_msg
+------------------------------------------------------------------------------
| Description : Stores a coded message in context data.
| Used for retransmissions (i.e. in case of time-outs, resume
| after suspension).
|
| Parameters : context - context data
| msg - coded message
+------------------------------------------------------------------------------
*/
void sm_allocate_and_copy_coded_msg(struct T_SM_CONTEXT_DATA *context,
U8 est_cause,
/*@in@*/ T_sdu *msg)
{
U32 msg_len;
#ifdef DEBUG_VERBOSE
(void)TRACE_FUNCTION("sm_allocate_and_copy_coded_msg");
#endif
msg_len = (U32)(msg->l_buf >> 3);
if (context->coded_msg != NULL)
{
sm_free_coded_msg(context);
}
TRACE_ASSERT(context->coded_msg == NULL);
/* Allocate space for T_sdu (l_buf and o_buf) + air interface message octets */
context->coded_msg = (T_sdu *)M_ALLOC(msg_len + (U32)offsetof(T_sdu, buf));
if (context->coded_msg == NULL)
{
return;
}
/* coded_msg->o_buf is always 0. So we store the only external parameter
* in there (est_cause). */
context->coded_msg->l_buf = msg->l_buf;
context->coded_msg->o_buf = (U16)est_cause;
memcpy(context->coded_msg->buf, &msg->buf[(msg->o_buf >> 3)], (size_t)msg_len);
}
/*
+------------------------------------------------------------------------------
| Function : sm_free_coded_msg
+------------------------------------------------------------------------------
| Description : Frees the coded message stored for this NSAPI, if any.
|
| Parameters : context - context data
+------------------------------------------------------------------------------
*/
void sm_free_coded_msg(struct T_SM_CONTEXT_DATA *context)
{
#ifdef DEBUG_VERBOSE
(void)TRACE_FUNCTION("sm_free_coded_msg");
#endif
if (context->coded_msg != NULL) {
sm_mfree(context->coded_msg);
}
context->coded_msg = NULL;
}
/*======================================================================
* Network Control Memory Handler Functions
*======================================================================*/
/*
+------------------------------------------------------------------------------
| Function : sm_nw_allocate_and_copy_*_pco
+------------------------------------------------------------------------------
| Description : Allocate and copy requested or negotiated PCO data structure.
|
| Parameters : context - context data
| pco_len - PCO data length
| pco - PCO data
+------------------------------------------------------------------------------
*/
void sm_nw_allocate_and_copy_requested_pco(/*@special@*/
struct T_SM_CONTEXT_DATA *context,
size_t /*@alt U8,U16@*/ pco_len,
/*@unique@*/ U8 *pco)
{
TRACE_ASSERT(context->requested_pco == NULL);
context->requested_pco = (T_SM_pco *)M_ALLOC((U32)(pco_len + 1));
TRACE_ASSERT(context->requested_pco != NULL);
context->requested_pco->c_pco_value = (U8)pco_len;
memcpy(context->requested_pco->pco_value, pco, (size_t)pco_len);
}
void sm_nw_allocate_and_copy_negotiated_pco(/*@special@*/
struct T_SM_CONTEXT_DATA *context,
size_t /*@alt U8@*/ pco_len,
/*@unique@*/ U8 *pco)
{
TRACE_ASSERT(context->negotiated_pco == NULL);
context->negotiated_pco = (T_SM_pco *)M_ALLOC((U32)(pco_len + 1));
TRACE_ASSERT(context->negotiated_pco != NULL);
context->negotiated_pco->c_pco_value = (U8)pco_len;
memcpy(context->negotiated_pco->pco_value, pco, (size_t)pco_len);
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_free_*_pco
+------------------------------------------------------------------------------
| Description : Free requested or negotiated PCO data structure
|
| Parameters : context - context data
+------------------------------------------------------------------------------
*/
void
sm_nw_free_requested_pco(/*@special@*/struct T_SM_CONTEXT_DATA *context)
{
if (context->requested_pco != NULL) {
sm_mfree(context->requested_pco);
context->requested_pco = NULL;
}
}
void
sm_nw_free_negotiated_pco(/*@special@*/struct T_SM_CONTEXT_DATA *context)
{
if (context->negotiated_pco != NULL) {
sm_mfree(context->negotiated_pco);
context->negotiated_pco = NULL;
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_allocate_and_copy_apn
+------------------------------------------------------------------------------
| Description : Allocate and copy APN data structure. Inserted into context
| data structure.
|
| Parameters : context - Context data
| apn - APN data structure
+------------------------------------------------------------------------------
*/
void sm_nw_allocate_and_copy_apn(/*@special@*/
struct T_SM_CONTEXT_DATA *context,
U8 c_apn, /*@unique@*/ U8 *apn)
{
#ifdef DEBUG_VERBOSE
(void)TRACE_FUNCTION("sm_nw_allocate_and_copy_apn");
#endif
TRACE_ASSERT(context->apn == NULL);
context->apn = (T_SMREG_apn *)M_ALLOC((U32)sizeof(T_SMREG_apn));
TRACE_ASSERT(context->apn != NULL);
context->apn->c_apn_buf = c_apn;
memcpy(context->apn->apn_buf, apn, (size_t)c_apn);
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_free_apn
+------------------------------------------------------------------------------
| Description : Free APN data structure
|
| Parameters : context - Context data
+------------------------------------------------------------------------------
*/
void sm_nw_free_apn(/*@special@*/ struct T_SM_CONTEXT_DATA *context)
{
#ifdef DEBUG_VERBOSE
(void)TRACE_FUNCTION("sm_nw_free_apn");
#endif
if (context->apn != NULL) {
sm_mfree(context->apn);
context->apn = NULL;
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_is_address_and_apn_equal
+------------------------------------------------------------------------------
| Description : Compare requested IP address and APN with incoming ditto
|
| Parameters : context - Context data
| address - incoming IP address
| v_apn - valid flag for APN
| apn - APN value (void if v_apn == FALSE)
+------------------------------------------------------------------------------
*/
BOOL sm_nw_is_address_and_apn_equal(struct T_SM_CONTEXT_DATA *context,
T_NAS_ip *context_address,
T_M_SM_address *msg_address,
U8 v_apn, T_M_SM_apn *apn)
{
/* Compare IP address */
if (context_address->ctrl_ip_address == NAS_is_ip_not_present) {
return FALSE;
} else if (msg_address->pdp_type_org == (U8)M_SM_IETF_ORG &&
context->pdp_type == msg_address->pdp_type_no)
{
if (context->pdp_type == (U8)SMREG_PDP_IPV4)
{
if (msg_address->c_add_info == (U8)NAS_SIZE_IPv4_ADDR &&
memcmp(context_address->ip_address.ipv4_addr.a4,
msg_address->add_info, (size_t)NAS_SIZE_IPv4_ADDR) == 0)
{
/* IP address equal: FALLTHROUGH */
} else {
return FALSE;
}
} else if (context->pdp_type == (U8)SMREG_PDP_IPV6)
{
if (msg_address->c_add_info == (U8)NAS_SIZE_IPv6_ADDR &&
memcmp(context_address->ip_address.ipv6_addr.a6,
msg_address->add_info, (size_t)NAS_SIZE_IPv6_ADDR) == 0)
{
/* IP address equal: FALLTHROUGH */
} else {
return FALSE;
}
} else { /* Bogus pdp_type */
return FALSE;
}
} else {
return FALSE;
}
/* Compare APN */
if (v_apn == (U8)TRUE) {
/* Incoming APN present: Requested APN must also be present, and have same length and values */
if (context->apn != NULL) {
if (context->apn->c_apn_buf == apn->c_apn_value) {
if (memcmp(context->apn->apn_buf, apn->apn_value,
(size_t)apn->c_apn_value) == 0) {
return TRUE;
}
}
}
return FALSE;
} else {
/* If incoming APN is absent, equality depends on the presence of a requested APN */
return (context->apn == NULL);
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_allocate_and_copy_requested_tft
+------------------------------------------------------------------------------
| Description : Allocate and copy TFT data structure. Inserted into context
| data structure.
|
| Parameters : context - Context data
| tft - TFT data structure
+------------------------------------------------------------------------------
*/
void sm_nw_allocate_and_copy_requested_tft(/*@special@*/
struct T_SM_CONTEXT_DATA *context,
/*@in@*/
T_NAS_tft *tft)
{
#ifdef DEBUG_VERBOSE
(void)TRACE_FUNCTION("sm_nw_allocate_and_copy_requested_tft");
#endif
/* Free TFT memory if a TFT was already present but with a different
* number of elements. */
if (context->requested_tft.ptr_tft_pf != NULL &&
context->requested_tft.c_tft_pf != tft->c_tft_pf)
{
sm_nw_free_requested_tft(context);
}
/* Allocate memory if TFT was not present before, or if it was freed above.*/
if (context->requested_tft.ptr_tft_pf == NULL)
{
context->requested_tft.c_tft_pf = tft->c_tft_pf;
context->requested_tft.ptr_tft_pf = (T_NAS_tft_pf *)
M_ALLOC((U32)sizeof(T_NAS_tft_pf) * (U32)context->requested_tft.c_tft_pf);
TRACE_ASSERT(context->requested_tft.ptr_tft_pf != NULL);
}
memcpy(context->requested_tft.ptr_tft_pf, tft->ptr_tft_pf,
sizeof(T_NAS_tft_pf) * (size_t)context->requested_tft.c_tft_pf);
context->requested_tft.tft_precence_mask = sm_tft_precence_mask(tft->ptr_tft_pf, tft->c_tft_pf);
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_allocate_active_tft
+------------------------------------------------------------------------------
| Description : Allocate active TFT data structure. Inserted into context
| data structure.
|
| Parameters : context - Context data
+------------------------------------------------------------------------------
*/
void sm_nw_allocate_active_tft(/*@special@*/struct T_SM_CONTEXT_DATA *context)
{
#ifdef DEBUG_VERBOSE
(void)TRACE_FUNCTION("sm_nw_allocate_active_tft");
#endif
TRACE_ASSERT (context->active_tft.ptr_tft_pf == NULL);
context->active_tft.c_tft_pf = (U8)0;
context->active_tft.ptr_tft_pf = (T_NAS_tft_pf *)
M_ALLOC((U32)sizeof(T_NAS_tft_pf) * (U32)NAS_SIZE_TFT_FILTER);
TRACE_ASSERT(context->active_tft.ptr_tft_pf != NULL);
context->active_tft.tft_precence_mask = (U8)0;
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_free_requested_tft
+------------------------------------------------------------------------------
| Description : Free TFT data structure
|
| Parameters : context - Context data
+------------------------------------------------------------------------------
*/
void sm_nw_free_requested_tft(/*@special@*/struct T_SM_CONTEXT_DATA *context)
{
#ifdef DEBUG_VERBOSE
(void)TRACE_FUNCTION("sm_nw_free_requested_tft");
#endif
if (context->requested_tft.ptr_tft_pf != NULL) {
sm_mfree(context->requested_tft.ptr_tft_pf);
context->requested_tft.ptr_tft_pf = NULL;
context->requested_tft.c_tft_pf = (U8)0;
context->requested_tft.tft_precence_mask = (U8)0;
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_free_active_tft
+------------------------------------------------------------------------------
| Description : Free TFT data structure
|
| Parameters : context - Context data
+------------------------------------------------------------------------------
*/
void sm_nw_free_active_tft(/*@special@*/struct T_SM_CONTEXT_DATA *context)
{
#ifdef DEBUG_VERBOSE
(void)TRACE_FUNCTION("sm_nw_free_active_tft");
#endif
if (context->active_tft.ptr_tft_pf != NULL) {
sm_mfree(context->active_tft.ptr_tft_pf);
context->active_tft.ptr_tft_pf = NULL;
context->active_tft.c_tft_pf = (U8)0;
context->active_tft.tft_precence_mask = (U8)0;
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_store_requested_address
+------------------------------------------------------------------------------
| Description : Utility function which stores the IP address requested from
| the network.
|
| Parameters : context - context data
| pdp_type - PDP type number
| ctrl_ip_address - IP address type
| ip_address - IP address (void if ctrl_ip_address == NAS_is_ip_not_present)
+------------------------------------------------------------------------------
*/
void sm_nw_store_requested_address(struct T_SM_CONTEXT_DATA *context,
U8 pdp_type,
T_NAS_ctrl_ip_address ctrl_ip_address,
T_NAS_ip_address *ip_address)
{
context->pdp_type = pdp_type;
context->requested_address.ctrl_ip_address = ctrl_ip_address;
if (ctrl_ip_address != NAS_is_ip_not_present) {
if (pdp_type == (U8)SMREG_PDP_PPP ||
(pdp_type == (U8)SMREG_PDP_IPV4 && ctrl_ip_address != NAS_is_ipv4) ||
(pdp_type == (U8)SMREG_PDP_IPV6 && ctrl_ip_address != NAS_is_ipv6)) {
(void)TRACE_ERROR("Mismatching pdp_type and ip_address controller field in SMREG_PDP_ACTIVATE_REQ - using union controller!");
}
switch (ctrl_ip_address)
{
case NAS_is_ipv4:
context->pdp_type = (U8)SMREG_PDP_IPV4;
memcpy(context->requested_address.ip_address.ipv4_addr.a4,
ip_address->ipv4_addr.a4, (size_t)NAS_SIZE_IPv4_ADDR);
break;
case NAS_is_ipv6:
context->pdp_type = (U8)SMREG_PDP_IPV6;
memcpy(context->requested_address.ip_address.ipv6_addr.a6,
ip_address->ipv6_addr.a6, (size_t)NAS_SIZE_IPv6_ADDR);
break;
default:
break;
}
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_store_negotiated_address
+------------------------------------------------------------------------------
| Description : Utility function which stores the address received from the
| network.
|
| Parameters : context - context data
| v_address - valid flag for address
| address - IP address (void if v_address == FALSE)
+------------------------------------------------------------------------------
*/
void sm_nw_store_negotiated_address(struct T_SM_CONTEXT_DATA *context,
T_M_SM_address *address,
U8 v_address)
{
if (v_address == (U8)TRUE && address->pdp_type_org == (U8)M_SM_IETF_ORG) {
/* Update PDP type from message */
context->pdp_type = address->pdp_type_no;
if (address->pdp_type_no == (U8)M_SM_IP4_TYPE) {
if (address->c_add_info != (U8)NAS_SIZE_IPv4_ADDR) {
(void)TRACE_EVENT_P1("Warning: IPv4 address has length %d != 4!",
(int)address->c_add_info);
}
context->negotiated_address.ctrl_ip_address = NAS_is_ipv4;
memcpy(&context->negotiated_address.ip_address, &address->add_info, (size_t)NAS_SIZE_IPv4_ADDR);
} else if (address->pdp_type_no == (U8)M_SM_IP6_TYPE) {
if (address->c_add_info != (U8)NAS_SIZE_IPv6_ADDR) {
(void)TRACE_EVENT_P1("Warning: IPv6 address has length %d != 16!",
(int)address->c_add_info);
}
context->negotiated_address.ctrl_ip_address = NAS_is_ipv6;
memcpy(&context->negotiated_address.ip_address, &address->add_info, (size_t)NAS_SIZE_IPv6_ADDR);
} else {
(void)TRACE_EVENT_P1("ERROR: Invalid PDP type %d; address discarded!",
address->pdp_type_no);
}
} else {
/* Check for static IP address allocation/request;
* PDP addr IE is not included in this case [3G 24.008, 9.5.2.1] */
switch (context->requested_address.ctrl_ip_address)
{
case NAS_is_ipv4:
context->pdp_type = (U8)SMREG_PDP_IPV4;
context->negotiated_address.ctrl_ip_address = NAS_is_ipv4;
memcpy(context->negotiated_address.ip_address.ipv4_addr.a4,
context->requested_address .ip_address.ipv4_addr.a4,
(size_t)NAS_SIZE_IPv4_ADDR);
break;
case NAS_is_ipv6:
context->pdp_type = (U8)SMREG_PDP_IPV6;
context->negotiated_address.ctrl_ip_address = NAS_is_ipv6;
memcpy(context->negotiated_address.ip_address.ipv6_addr.a6,
context->requested_address .ip_address.ipv6_addr.a6,
(size_t)NAS_SIZE_IPv6_ADDR);
break;
default:
/* PPP or other non-IP address context; i.e. no static address alloc. */
context->negotiated_address.ctrl_ip_address = NAS_is_ip_not_present;
}
}
}
/*
+------------------------------------------------------------------------------
| Function : sm_nw_copy_negotiated_address_to_requested
+------------------------------------------------------------------------------
| Description : Utility function which copies the address received from the
| network to be the requested address. Used for context
| reactivations, which must use the negotiated IP address.
|
| Parameters : context - context data
+------------------------------------------------------------------------------
*/
void sm_nw_copy_negotiated_address_to_requested(struct T_SM_CONTEXT_DATA *context)
{
sm_nw_store_requested_address(context, context->pdp_type,
context->negotiated_address.ctrl_ip_address,
&context->negotiated_address.ip_address);
}
/*
+------------------------------------------------------------------------------
| Function : sm_is_address_changed_with_reactivation
+------------------------------------------------------------------------------
| Description : Utility function which compares the address of the air message
| and the address already stored in the context. This function
| is useful only in PDP REACTIVATION cases. If the addresses
| are not equal the function returns false and the pdp context
| gets deactivated.
|
| Parameters : context - context data, air message address
+------------------------------------------------------------------------------
*/
BOOL sm_is_address_changed_with_reactivation(struct T_SM_CONTEXT_DATA *context,
T_M_SM_address *address,
U8 v_address)
{
BOOL result = FALSE;
if (sm_is_context_pending_reactivation(context))
{
if (v_address == (U8)TRUE && address->pdp_type_org == (U8)M_SM_IETF_ORG)
{
if ( (address->pdp_type_no == (U8)M_SM_IP4_TYPE) &&
(context->negotiated_address.ctrl_ip_address == NAS_is_ipv4) )
{
if (memcmp(&context->negotiated_address.ip_address,
&address->add_info, (size_t)NAS_SIZE_IPv4_ADDR) != 0)
{
result = TRUE;
}
} else if ( (address->pdp_type_no == (U8)M_SM_IP6_TYPE) &&
(context->negotiated_address.ctrl_ip_address == NAS_is_ipv6) )
{
if (memcmp(&context->negotiated_address.ip_address,
&address->add_info, (size_t)NAS_SIZE_IPv6_ADDR) != 0)
{
result = TRUE;
}
}
}
/* Clear the pending reactivation flag. We don't need this anymore. */
sm_set_context_pending_reactivation(context, FALSE);
}
if (result == TRUE) {
(void)TRACE_EVENT_P1( "PDP address changed with reactivation. Deactivate nsapi %d",
context->nsapi );
}
return result;
}
/*==== END OF FILE ==========================================================*/