diff src/g23m-gprs/sm/sm_memory_handler.c @ 183:219afcfc6250

src/g23m-gprs: initial import from TCS3.2/LoCosto
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 13 Oct 2016 04:24:13 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gprs/sm/sm_memory_handler.c	Thu Oct 13 04:24:13 2016 +0000
@@ -0,0 +1,888 @@
+/*----------------------------------------------------------------------------
+|  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 ==========================================================*/