/****************************************************************************
 **                                                                        **
 ** Name:  _esm_msg_decode_header()                                  **
 **                                                                        **
 ** Description: Decode header of EPS Mobility Management message.         **
 **    The protocol discriminator and the security header type   **
 **    have already been decoded.                                **
 **                                                                        **
 ** Inputs:  buffer:  Pointer to the buffer containing the ESM   **
 **       message                                    **
 **      len:   Number of bytes that should be decoded     **
 **    Others:  None                                       **
 **                                                                        **
 ** Outputs:   header:  The ESM message header to be filled        **
 **      Return:  The size of the header if data have been   **
 **       successfully decoded;                      **
 **       A negative error code otherwise.           **
 **    Others:  None                                       **
 **                                                                        **
 ***************************************************************************/
static int
_esm_msg_decode_header (
  esm_msg_header_t * header,
  const uint8_t * buffer,
  uint32_t len)
{
  int                                     size = 0;

  /*
   * Check the buffer length
   */
  if (len < sizeof (esm_msg_header_t)) {
    return (TLV_DECODE_BUFFER_TOO_SHORT);
  }

  /*
   * Decode the EPS bearer identity and the protocol discriminator
   */
  DECODE_U8 (buffer + size, *(uint8_t *) (header), size);
  /*
   * Decode the procedure transaction identity
   */
  DECODE_U8 (buffer + size, header->procedure_transaction_identity, size);
  /*
   * Decode the message type
   */
  DECODE_U8 (buffer + size, header->message_type, size);

  /*
   * Check the protocol discriminator
   */
  if (header->protocol_discriminator != EPS_SESSION_MANAGEMENT_MESSAGE) {
    LOG_TRACE (ERROR, "ESM-MSG   - Unexpected protocol discriminator: 0x%x", header->protocol_discriminator);
    return (TLV_DECODE_PROTOCOL_NOT_SUPPORTED);
  }

  return (size);
}
int decode_ue_network_capability(UeNetworkCapability *uenetworkcapability, uint8_t iei, uint8_t *buffer, uint32_t len)
{
    int decoded = 0;
    uint8_t ielen = 0;
    if (iei > 0)
    {
        CHECK_IEI_DECODER(iei, *buffer);
        decoded++;
    }
    DECODE_U8(buffer + decoded, ielen, decoded);

    memset(uenetworkcapability, 0, sizeof(UeNetworkCapability));

    LOG_TRACE(INFO, "decode_ue_network_capability len = %d",ielen);
    CHECK_LENGTH_DECODER(len - decoded, ielen);
    uenetworkcapability->eea = *(buffer + decoded);
    decoded++;
    uenetworkcapability->eia = *(buffer + decoded);
    decoded++;

    /* Parts below not mandatory and may not be present */
    if (ielen > 2) {
        uenetworkcapability->uea = *(buffer + decoded);
        decoded++;

        if (ielen > 3) {
            uenetworkcapability->ucs2 = (*(buffer + decoded) >> 7) & 0x1;
            uenetworkcapability->uia = *(buffer + decoded) & 0x7f;
            decoded++;
            uenetworkcapability->umts_present =1;
            LOG_TRACE(INFO, "uenetworkcapability decoded UMTS\n");

            if (ielen > 4) {
                uenetworkcapability->spare = (*(buffer + decoded) >> 5) & 0x7;
                uenetworkcapability->csfb  = (*(buffer + decoded) >> 4) & 0x1;
                uenetworkcapability->lpp   = (*(buffer + decoded) >> 3) & 0x1;
                uenetworkcapability->lcs   = (*(buffer + decoded) >> 2) & 0x1;
                uenetworkcapability->srvcc = (*(buffer + decoded) >> 1) & 0x1;
                uenetworkcapability->nf    = *(buffer + decoded) & 0x1;
                decoded++;
                uenetworkcapability->gprs_present =1;
                LOG_TRACE(INFO, "uenetworkcapability decoded GPRS\n");
            }