FreeCalypso > hg > fc-magnetite
view src/g23m-gprs/sm/sm_memory_handler.c @ 663:cf1cfe12a54a
AT@SPENH command implemented in aci3
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 24 May 2020 06:53:25 +0000 |
parents | 219afcfc6250 |
children |
line wrap: on
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 ==========================================================*/