/*
 * Copyright 2013-2019 Software Radio Systems Limited
 *
 * This file is part of srsLTE.
 *
 * srsLTE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * srsLTE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * A copy of the GNU Affero General Public License can be found in
 * the LICENSE file in the top-level directory of this distribution
 * and at http://www.gnu.org/licenses/.
 *
 */

#include "srslte/asn1/liblte_s1ap.h"
# include <stdio.h>
# include <stdarg.h>
# include <math.h>

/*******************************************************************************
                              LOGGING
*******************************************************************************/

static log_handler_t log_handler;
static void *callback_ctx = NULL;

void liblte_log_register_handler(void *ctx, log_handler_t handler) {
  log_handler  = handler;
  callback_ctx = ctx;
}

static void liblte_log_print(const char *format, ...) {
  va_list   args;
  va_start(args, format);
  if (log_handler) {
    char *args_msg = NULL;
    if(vasprintf(&args_msg, format, args) > 0) {
      log_handler(callback_ctx, args_msg);
    }
    if (args_msg) {
      free(args_msg);
    }
  } else {
    vprintf(format, args);
  }
  va_end(args);
}

/*******************************************************************************
/* ProtocolIE Criticality ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_criticality(
  LIBLTE_S1AP_CRITICALITY_ENUM                                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 2);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_criticality(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CRITICALITY_ENUM                                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);
    err = LIBLTE_SUCCESS;
  }
  return err;
}


/*******************************************************************************
/* ProtocolIE local INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_local(
  LIBLTE_S1AP_LOCAL_STRUCT                                           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->local
    // lb:0, ub:65535
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (2*8)-16);
    liblte_value_2_bits(ie->local, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_local(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LOCAL_STRUCT                                           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->local
    // lb:0, ub:65535
    liblte_align_up(ptr, 8);
    ie->local = (uint16_t)liblte_bits_2_value(ptr, 2.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}


/*******************************************************************************
/* ProtocolIE PrivateIE_ID CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_privateie_id(
  LIBLTE_S1AP_PRIVATEIE_ID_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_PRIVATEIE_ID_CHOICE_LOCAL) {
      if(liblte_s1ap_pack_local(&ie->choice.local, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_PRIVATEIE_ID_CHOICE_GLOBAL) {
      } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_privateie_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PRIVATEIE_ID_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Choice type
    ie->choice_type = (LIBLTE_S1AP_PRIVATEIE_ID_CHOICE_ENUM)liblte_bits_2_value(ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_PRIVATEIE_ID_CHOICE_LOCAL) {
      if(liblte_s1ap_unpack_local(ptr, &ie->choice.local) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_PRIVATEIE_ID_CHOICE_GLOBAL) {
      } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProtocolExtensionID INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolextensionid(
  LIBLTE_S1AP_PROTOCOLEXTENSIONID_STRUCT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ProtocolExtensionID
    // lb:0, ub:65535
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (2*8)-16);
    liblte_value_2_bits(ie->ProtocolExtensionID, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolextensionid(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROTOCOLEXTENSIONID_STRUCT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ProtocolExtensionID
    // lb:0, ub:65535
    liblte_align_up(ptr, 8);
    ie->ProtocolExtensionID = (uint16_t)liblte_bits_2_value(ptr, 2.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TriggeringMessage ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_triggeringmessage(
  LIBLTE_S1AP_TRIGGERINGMESSAGE_ENUM                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 2);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_triggeringmessage(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TRIGGERINGMESSAGE_ENUM                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_TRIGGERINGMESSAGE_ENUM)liblte_bits_2_value(ptr, 2);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Presence ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_presence(
  LIBLTE_S1AP_PRESENCE_ENUM                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 2);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_presence(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PRESENCE_ENUM                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_PRESENCE_ENUM)liblte_bits_2_value(ptr, 2);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProtocolIE_ID INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolie_id(
  LIBLTE_S1AP_PROTOCOLIE_ID_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ProtocolIE_ID
    // lb:0, ub:65535
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (2*8)-16);
    liblte_value_2_bits(ie->ProtocolIE_ID, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolie_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROTOCOLIE_ID_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ProtocolIE_ID
    // lb:0, ub:65535
    liblte_align_up(ptr, 8);
    ie->ProtocolIE_ID = (uint16_t)liblte_bits_2_value(ptr, 2.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProcedureCode INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_procedurecode(
  LIBLTE_S1AP_PROCEDURECODE_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ProcedureCode
    // lb:0, ub:255
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-8);
    liblte_value_2_bits(ie->ProcedureCode, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_procedurecode(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROCEDURECODE_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ProcedureCode
    // lb:0, ub:255
    liblte_align_up(ptr, 8);
    ie->ProcedureCode = (uint8_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProtocolIE_Field SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolie_field(
  LIBLTE_S1AP_PROTOCOLIE_FIELD_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_pack_protocolie_id(&ie->id, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum - ie->criticality
    liblte_value_2_bits(ie->criticality, ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolie_field(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROTOCOLIE_FIELD_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_unpack_protocolie_id(ptr, &ie->id) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum - ie->criticality
    ie->criticality = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProtocolExtensionField SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolextensionfield(
  LIBLTE_S1AP_PROTOCOLEXTENSIONFIELD_STRUCT                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_pack_protocolextensionid(&ie->id, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum - ie->criticality
    liblte_value_2_bits(ie->criticality, ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolextensionfield(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROTOCOLEXTENSIONFIELD_STRUCT                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_unpack_protocolextensionid(ptr, &ie->id) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum - ie->criticality
    ie->criticality = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProtocolIE_FieldPair SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolie_fieldpair(
  LIBLTE_S1AP_PROTOCOLIE_FIELDPAIR_STRUCT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_pack_protocolie_id(&ie->id, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum - ie->firstCriticality
    liblte_value_2_bits(ie->firstCriticality, ptr, 2);


    // Enum - ie->secondCriticality
    liblte_value_2_bits(ie->secondCriticality, ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolie_fieldpair(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROTOCOLIE_FIELDPAIR_STRUCT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_unpack_protocolie_id(ptr, &ie->id) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum - ie->firstCriticality
    ie->firstCriticality = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);


    // Enum - ie->secondCriticality
    ie->secondCriticality = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProtocolExtensionContainer DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolextensioncontainer(
  LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ProtocolExtensionContainer pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_protocolextensionfield(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolextensioncontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROTOCOLEXTENSIONCONTAINER_STRUCT                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ProtocolExtensionContainer unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolextensionfield(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProtocolIE_ContainerPair DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:0, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolie_containerpair(
  LIBLTE_S1AP_PROTOCOLIE_CONTAINERPAIR_STRUCT                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ProtocolIE_ContainerPair pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-0, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_protocolie_fieldpair(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolie_containerpair(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROTOCOLIE_CONTAINERPAIR_STRUCT                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 0;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ProtocolIE_ContainerPair unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_fieldpair(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProtocolIE_ContainerPairList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:None, ub:None
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolie_containerpairlist(
  LIBLTE_S1AP_PROTOCOLIE_CONTAINERPAIRLIST_STRUCT                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ProtocolIE_ContainerPairList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    if(ie->len < 128) {
      liblte_value_2_bits(0,       ptr, 1);
      liblte_value_2_bits(ie->len, ptr, 7);
    } else if(ie->len < 16383) {
      liblte_value_2_bits(1,       ptr, 1);
      liblte_value_2_bits(0,       ptr, 1);
      liblte_value_2_bits(ie->len, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of bits
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_protocolie_containerpair(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolie_containerpairlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROTOCOLIE_CONTAINERPAIRLIST_STRUCT                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->len = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->len = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of bits
      }
    }
    if(ie->len > 32) {
      liblte_log_print("ProtocolIE_ContainerPairList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_containerpair(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PrivateIE_Field SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_privateie_field(
  LIBLTE_S1AP_PRIVATEIE_FIELD_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_pack_privateie_id(&ie->id, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum - ie->criticality
    liblte_value_2_bits(ie->criticality, ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_privateie_field(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PRIVATEIE_FIELD_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_unpack_privateie_id(ptr, &ie->id) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum - ie->criticality
    ie->criticality = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ProtocolIE_SingleContainer SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolie_singlecontainer(
  LIBLTE_S1AP_PROTOCOLIE_SINGLECONTAINER_STRUCT                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_pack_protocolie_id(&ie->id, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum - ie->criticality
    liblte_value_2_bits(ie->criticality, ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolie_singlecontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PROTOCOLIE_SINGLECONTAINER_STRUCT                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {

    if(liblte_s1ap_unpack_protocolie_id(ptr, &ie->id) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum - ie->criticality
    ie->criticality = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PrivateIE_Container DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_privateie_container(
  LIBLTE_S1AP_PRIVATEIE_CONTAINER_STRUCT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("PrivateIE_Container pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_privateie_field(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_privateie_container(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PRIVATEIE_CONTAINER_STRUCT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("PrivateIE_Container unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_privateie_field(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE BitRate INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_bitrate(
  LIBLTE_S1AP_BITRATE_STRUCT                                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->BitRate
    // lb:0, ub:10000000000
    // Range > 65536 - encoded based on value
    {
      uint32_t n_bits   = floor(log2(ie->BitRate-0)+1);
      uint32_t n_octets = (n_bits+7)/8;
      liblte_value_2_bits(n_octets-1, ptr, 3);
      liblte_align_up_zero(ptr, 8);
      liblte_value_2_bits(0, ptr, (n_octets*8)-n_bits);
      liblte_value_2_bits(ie->BitRate-0, ptr, n_bits);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_bitrate(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_BITRATE_STRUCT                                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->BitRate
    // lb:0, ub:10000000000
    // Range > 65536 - encoded based on value
    {
      uint32_t n_octets = liblte_bits_2_value(ptr, 3) + 1;
      liblte_align_up(ptr, 8);
      ie->BitRate = liblte_bits_2_value(ptr, n_octets*8) + 0;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CauseMisc ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_causemisc(
  LIBLTE_S1AP_CAUSEMISC_ENUM_EXT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseMisc error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_causemisc(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CAUSEMISC_ENUM_EXT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseMisc error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CAUSEMISC_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CauseRadioNetwork ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_causeradionetwork(
  LIBLTE_S1AP_CAUSERADIONETWORK_ENUM_EXT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseRadioNetwork error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 6);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_causeradionetwork(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CAUSERADIONETWORK_ENUM_EXT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseRadioNetwork error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CAUSERADIONETWORK_ENUM)liblte_bits_2_value(ptr, 6);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CauseNas ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_causenas(
  LIBLTE_S1AP_CAUSENAS_ENUM_EXT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseNas error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_causenas(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CAUSENAS_ENUM_EXT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseNas error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CAUSENAS_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CellIdentity STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellidentity(
  LIBLTE_S1AP_CELLIDENTITY_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - CellIdentity
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_CELLIDENTITY_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellidentity(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELLIDENTITY_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - CellIdentity
    liblte_align_up(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_CELLIDENTITY_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000PDU DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000pdu(
  LIBLTE_S1AP_CDMA2000PDU_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000PDU
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000pdu(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000PDU_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000PDU
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000SectorID DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000sectorid(
  LIBLTE_S1AP_CDMA2000SECTORID_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000SectorID
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000sectorid(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000SECTORID_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000SectorID
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000HORequiredIndication ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000horequiredindication(
  LIBLTE_S1AP_CDMA2000HOREQUIREDINDICATION_ENUM_EXT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cdma2000HORequiredIndication error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000horequiredindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000HOREQUIREDINDICATION_ENUM_EXT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cdma2000HORequiredIndication error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CDMA2000HOREQUIREDINDICATION_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000OneXMSI DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000onexmsi(
  LIBLTE_S1AP_CDMA2000ONEXMSI_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000OneXMSI
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000onexmsi(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000ONEXMSI_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000OneXMSI
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000OneXRAND DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000onexrand(
  LIBLTE_S1AP_CDMA2000ONEXRAND_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000OneXRAND
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000onexrand(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000ONEXRAND_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000OneXRAND
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CNDomain ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cndomain(
  LIBLTE_S1AP_CNDOMAIN_ENUM                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 1);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cndomain(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CNDOMAIN_ENUM                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_CNDOMAIN_ENUM)liblte_bits_2_value(ptr, 1);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Correlation_ID STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_correlation_id(
  LIBLTE_S1AP_CORRELATION_ID_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - Correlation-ID
    if(LIBLTE_S1AP_CORRELATION_ID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_CORRELATION_ID_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_correlation_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CORRELATION_ID_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - Correlation-ID
    if(LIBLTE_S1AP_CORRELATION_ID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_CORRELATION_ID_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE AdditionalCSFallbackIndicator ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_additionalcsfallbackindicator(
  LIBLTE_S1AP_ADDITIONALCSFALLBACKINDICATOR_ENUM_EXT                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("AdditionalCSFallbackIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_additionalcsfallbackindicator(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ADDITIONALCSFALLBACKINDICATOR_ENUM_EXT                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("AdditionalCSFallbackIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_ADDITIONALCSFALLBACKINDICATOR_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE DL_Forwarding ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_dl_forwarding(
  LIBLTE_S1AP_DL_FORWARDING_ENUM_EXT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("DL_Forwarding error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_dl_forwarding(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_DL_FORWARDING_ENUM_EXT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("DL_Forwarding error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_DL_FORWARDING_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Data_Forwarding_Not_Possible ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_data_forwarding_not_possible(
  LIBLTE_S1AP_DATA_FORWARDING_NOT_POSSIBLE_ENUM_EXT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Data_Forwarding_Not_Possible error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_data_forwarding_not_possible(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_DATA_FORWARDING_NOT_POSSIBLE_ENUM_EXT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Data_Forwarding_Not_Possible error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_DATA_FORWARDING_NOT_POSSIBLE_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EmergencyAreaID STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_emergencyareaid(
  LIBLTE_S1AP_EMERGENCYAREAID_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - EmergencyAreaID
    if(LIBLTE_S1AP_EMERGENCYAREAID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_EMERGENCYAREAID_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_emergencyareaid(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EMERGENCYAREAID_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - EmergencyAreaID
    if(LIBLTE_S1AP_EMERGENCYAREAID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_EMERGENCYAREAID_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}


/*******************************************************************************
/* ProtocolIE macroENB_ID STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_macroenb_id(
  LIBLTE_S1AP_MACROENB_ID_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - macroENB-ID
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_macroenb_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MACROENB_ID_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - macroENB-ID
    liblte_align_up(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}



/*******************************************************************************
/* ProtocolIE homeENB_ID STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_homeenb_id(
  LIBLTE_S1AP_HOMEENB_ID_STRUCT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - homeENB-ID
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_HOMEENB_ID_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_homeenb_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_HOMEENB_ID_STRUCT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - homeENB-ID
    liblte_align_up(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_HOMEENB_ID_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}


/*******************************************************************************
/* ProtocolIE ENB_ID CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enb_id(
  LIBLTE_S1AP_ENB_ID_STRUCT                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ENB_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_ENB_ID_CHOICE_MACROENB_ID) {
      if(liblte_s1ap_pack_macroenb_id(&ie->choice.macroENB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_ENB_ID_CHOICE_HOMEENB_ID) {
      if(liblte_s1ap_pack_homeenb_id(&ie->choice.homeENB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enb_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ENB_ID_STRUCT                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ENB_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_ENB_ID_CHOICE_ENUM)liblte_bits_2_value(ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_ENB_ID_CHOICE_MACROENB_ID) {
      if(liblte_s1ap_unpack_macroenb_id(ptr, &ie->choice.macroENB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_ENB_ID_CHOICE_HOMEENB_ID) {
      if(liblte_s1ap_unpack_homeenb_id(ptr, &ie->choice.homeENB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ENBname PrintableString
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbname(
  LIBLTE_S1AP_ENBNAME_STRUCT                                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Printable string - ENBname
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ENBname error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Length
    liblte_value_2_bits(ie->n_octets-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbname(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ENBNAME_STRUCT                                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Printable string - ENBname
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ENBname error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Length
    ie->n_octets = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);

    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EncryptionAlgorithms STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_encryptionalgorithms(
  LIBLTE_S1AP_ENCRYPTIONALGORITHMS_STRUCT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - EncryptionAlgorithms
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("EncryptionAlgorithms error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_ENCRYPTIONALGORITHMS_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_encryptionalgorithms(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ENCRYPTIONALGORITHMS_STRUCT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - EncryptionAlgorithms
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("EncryptionAlgorithms error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_ENCRYPTIONALGORITHMS_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EventType ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_eventtype(
  LIBLTE_S1AP_EVENTTYPE_ENUM_EXT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("EventType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 2);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_eventtype(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EVENTTYPE_ENUM_EXT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("EventType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_EVENTTYPE_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ExtendedRNC_ID INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_extendedrnc_id(
  LIBLTE_S1AP_EXTENDEDRNC_ID_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ExtendedRNC_ID
    // lb:4096, ub:65535
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (2*8)-16);
    liblte_value_2_bits(ie->ExtendedRNC_ID, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_extendedrnc_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EXTENDEDRNC_ID_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ExtendedRNC_ID
    // lb:4096, ub:65535
    liblte_align_up(ptr, 8);
    ie->ExtendedRNC_ID = (uint16_t)liblte_bits_2_value(ptr, 2.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ForbiddenInterRATs ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_forbiddeninterrats(
  LIBLTE_S1AP_FORBIDDENINTERRATS_ENUM_EXT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ForbiddenInterRATs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_forbiddeninterrats(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_FORBIDDENINTERRATS_ENUM_EXT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ForbiddenInterRATs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_FORBIDDENINTERRATS_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE GWContextReleaseIndication ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_gwcontextreleaseindication(
  LIBLTE_S1AP_GWCONTEXTRELEASEINDICATION_ENUM_EXT                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("GWContextReleaseIndication error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_gwcontextreleaseindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_GWCONTEXTRELEASEINDICATION_ENUM_EXT                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("GWContextReleaseIndication error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_GWCONTEXTRELEASEINDICATION_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE HFN INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_hfn(
  LIBLTE_S1AP_HFN_STRUCT                                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->HFN
    // lb:0, ub:1048575
    // Range > 65536 - encoded based on value
    {
      uint32_t n_bits   = floor(log2(ie->HFN-0)+1);
      uint32_t n_octets = (n_bits+7)/8;
      liblte_value_2_bits(n_octets-1, ptr, 2);
      liblte_align_up_zero(ptr, 8);
      liblte_value_2_bits(0, ptr, (n_octets*8)-n_bits);
      liblte_value_2_bits(ie->HFN-0, ptr, n_bits);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_hfn(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_HFN_STRUCT                                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->HFN
    // lb:0, ub:1048575
    // Range > 65536 - encoded based on value
    {
      uint32_t n_octets = liblte_bits_2_value(ptr, 2) + 1;
      liblte_align_up(ptr, 8);
      ie->HFN = liblte_bits_2_value(ptr, n_octets*8) + 0;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE IMSI DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_imsi(
  LIBLTE_S1AP_IMSI_STRUCT                                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // max length of IE buffer is 8, so limit
    if (ie->n_octets > 7) {
      printf("Length in struct exceeds buffer (%d > 7).\n", ie->n_octets);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Dynamic octet string - IMSI
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_imsi(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_IMSI_STRUCT                                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - IMSI
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE InterfacesToTrace STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_interfacestotrace(
  LIBLTE_S1AP_INTERFACESTOTRACE_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - InterfacesToTrace
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_INTERFACESTOTRACE_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_interfacestotrace(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_INTERFACESTOTRACE_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - InterfacesToTrace
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_INTERFACESTOTRACE_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LAC STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lac(
  LIBLTE_S1AP_LAC_STRUCT                                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - LAC
    if(LIBLTE_S1AP_LAC_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_LAC_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lac(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LAC_STRUCT                                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - LAC
    if(LIBLTE_S1AP_LAC_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_LAC_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LastVisitedUTRANCellInformation DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lastvisitedutrancellinformation(
  LIBLTE_S1AP_LASTVISITEDUTRANCELLINFORMATION_STRUCT                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - LastVisitedUTRANCellInformation
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lastvisitedutrancellinformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LASTVISITEDUTRANCELLINFORMATION_STRUCT                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - LastVisitedUTRANCellInformation
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE L3_Information DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_l3_information(
  LIBLTE_S1AP_L3_INFORMATION_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - L3-Information
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_l3_information(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_L3_INFORMATION_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - L3-Information
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LHN_ID DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lhn_id(
  LIBLTE_S1AP_LHN_ID_STRUCT                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - LHN-ID
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lhn_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LHN_ID_STRUCT                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - LHN-ID
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LoggingDuration ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_loggingduration(
  LIBLTE_S1AP_LOGGINGDURATION_ENUM                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 3);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_loggingduration(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LOGGINGDURATION_ENUM                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_LOGGINGDURATION_ENUM)liblte_bits_2_value(ptr, 3);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MDT_Activation ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mdt_activation(
  LIBLTE_S1AP_MDT_ACTIVATION_ENUM_EXT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("MDT_Activation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 2);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mdt_activation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MDT_ACTIVATION_ENUM_EXT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("MDT_Activation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_MDT_ACTIVATION_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ManagementBasedMDTAllowed ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_managementbasedmdtallowed(
  LIBLTE_S1AP_MANAGEMENTBASEDMDTALLOWED_ENUM_EXT                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ManagementBasedMDTAllowed error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_managementbasedmdtallowed(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MANAGEMENTBASEDMDTALLOWED_ENUM_EXT                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ManagementBasedMDTAllowed error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_MANAGEMENTBASEDMDTALLOWED_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PrivacyIndicator ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_privacyindicator(
  LIBLTE_S1AP_PRIVACYINDICATOR_ENUM_EXT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("PrivacyIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_privacyindicator(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PRIVACYINDICATOR_ENUM_EXT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("PrivacyIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_PRIVACYINDICATOR_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MeasurementsToActivate STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_measurementstoactivate(
  LIBLTE_S1AP_MEASUREMENTSTOACTIVATE_STRUCT                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - MeasurementsToActivate
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MEASUREMENTSTOACTIVATE_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_measurementstoactivate(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MEASUREMENTSTOACTIVATE_STRUCT                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - MeasurementsToActivate
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MEASUREMENTSTOACTIVATE_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MessageIdentifier STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_messageidentifier(
  LIBLTE_S1AP_MESSAGEIDENTIFIER_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - MessageIdentifier
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MESSAGEIDENTIFIER_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_messageidentifier(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGEIDENTIFIER_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - MessageIdentifier
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MESSAGEIDENTIFIER_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MMEname PrintableString
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmename(
  LIBLTE_S1AP_MMENAME_STRUCT                                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Printable string - MMEname
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("MMEname error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Length
    liblte_value_2_bits(ie->n_octets-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mmename(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MMENAME_STRUCT                                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Printable string - MMEname
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("MMEname error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Length
    ie->n_octets = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);

    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MME_Group_ID STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mme_group_id(
  LIBLTE_S1AP_MME_GROUP_ID_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - MME-Group-ID
    if(LIBLTE_S1AP_MME_GROUP_ID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MME_GROUP_ID_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mme_group_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MME_GROUP_ID_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - MME-Group-ID
    if(LIBLTE_S1AP_MME_GROUP_ID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MME_GROUP_ID_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MME_UE_S1AP_ID INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mme_ue_s1ap_id(
  LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->MME_UE_S1AP_ID
    // lb:0, ub:4294967295
    // Range > 65536 - encoded based on value
    {
      uint32_t n_bits   = floor(log2(ie->MME_UE_S1AP_ID-0)+1);
      uint32_t n_octets = (n_bits+7)/8;
      liblte_value_2_bits(n_octets-1, ptr, 2);
      liblte_align_up_zero(ptr, 8);
      liblte_value_2_bits(0, ptr, (n_octets*8)-n_bits);
      liblte_value_2_bits(ie->MME_UE_S1AP_ID-0, ptr, n_bits);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mme_ue_s1ap_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->MME_UE_S1AP_ID
    // lb:0, ub:4294967295
    // Range > 65536 - encoded based on value
    {
      uint32_t n_octets = liblte_bits_2_value(ptr, 2) + 1;
      liblte_align_up(ptr, 8);
      ie->MME_UE_S1AP_ID = liblte_bits_2_value(ptr, n_octets*8) + 0;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MSClassmark2 DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_msclassmark2(
  LIBLTE_S1AP_MSCLASSMARK2_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - MSClassmark2
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_msclassmark2(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MSCLASSMARK2_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - MSClassmark2
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE NAS_PDU DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_nas_pdu(
  LIBLTE_S1AP_NAS_PDU_STRUCT                                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - NAS-PDU
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_nas_pdu(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_NAS_PDU_STRUCT                                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - NAS-PDU
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE NASSecurityParameterstoE_UTRAN DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_nassecurityparameterstoe_utran(
  LIBLTE_S1AP_NASSECURITYPARAMETERSTOE_UTRAN_STRUCT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - NASSecurityParameterstoE-UTRAN
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_nassecurityparameterstoe_utran(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_NASSECURITYPARAMETERSTOE_UTRAN_STRUCT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - NASSecurityParameterstoE-UTRAN
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE NumberOfBroadcasts INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_numberofbroadcasts(
  LIBLTE_S1AP_NUMBEROFBROADCASTS_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->NumberOfBroadcasts
    // lb:0, ub:65535
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (2*8)-16);
    liblte_value_2_bits(ie->NumberOfBroadcasts, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_numberofbroadcasts(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_NUMBEROFBROADCASTS_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->NumberOfBroadcasts
    // lb:0, ub:65535
    liblte_align_up(ptr, 8);
    ie->NumberOfBroadcasts = (uint16_t)liblte_bits_2_value(ptr, 2.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE OverloadAction ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadaction(
  LIBLTE_S1AP_OVERLOADACTION_ENUM_EXT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("OverloadAction error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_overloadaction(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_OVERLOADACTION_ENUM_EXT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("OverloadAction error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_OVERLOADACTION_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PagingDRX ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pagingdrx(
  LIBLTE_S1AP_PAGINGDRX_ENUM_EXT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("PagingDRX error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 2);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pagingdrx(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PAGINGDRX_ENUM_EXT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("PagingDRX error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_PAGINGDRX_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PDCP_SN INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pdcp_sn(
  LIBLTE_S1AP_PDCP_SN_STRUCT                                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->PDCP_SN
    // lb:0, ub:4095
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (2*8)-12);
    liblte_value_2_bits(ie->PDCP_SN, ptr, 12);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pdcp_sn(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PDCP_SN_STRUCT                                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->PDCP_SN
    // lb:0, ub:4095
    liblte_align_up(ptr, 8);
    ie->PDCP_SN = (uint16_t)liblte_bits_2_value(ptr, 2*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Port_Number STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_port_number(
  LIBLTE_S1AP_PORT_NUMBER_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - Port-Number
    if(LIBLTE_S1AP_PORT_NUMBER_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_PORT_NUMBER_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_port_number(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PORT_NUMBER_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - Port-Number
    if(LIBLTE_S1AP_PORT_NUMBER_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_PORT_NUMBER_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Pre_emptionVulnerability ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pre_emptionvulnerability(
  LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_ENUM                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 1);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pre_emptionvulnerability(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_ENUM                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_ENUM)liblte_bits_2_value(ptr, 1);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PS_ServiceNotAvailable ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ps_servicenotavailable(
  LIBLTE_S1AP_PS_SERVICENOTAVAILABLE_ENUM_EXT                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("PS_ServiceNotAvailable error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ps_servicenotavailable(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PS_SERVICENOTAVAILABLE_ENUM_EXT                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("PS_ServiceNotAvailable error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_PS_SERVICENOTAVAILABLE_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ReceiveStatusofULPDCPSDUs STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_receivestatusofulpdcpsdus(
  LIBLTE_S1AP_RECEIVESTATUSOFULPDCPSDUS_STRUCT                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - ReceiveStatusofULPDCPSDUs
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_RECEIVESTATUSOFULPDCPSDUS_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_receivestatusofulpdcpsdus(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RECEIVESTATUSOFULPDCPSDUS_STRUCT                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - ReceiveStatusofULPDCPSDUs
    liblte_align_up(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_RECEIVESTATUSOFULPDCPSDUS_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RelativeMMECapacity INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_relativemmecapacity(
  LIBLTE_S1AP_RELATIVEMMECAPACITY_STRUCT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->RelativeMMECapacity
    // lb:0, ub:255
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-8);
    liblte_value_2_bits(ie->RelativeMMECapacity, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_relativemmecapacity(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RELATIVEMMECAPACITY_STRUCT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->RelativeMMECapacity
    // lb:0, ub:255
    liblte_align_up(ptr, 8);
    ie->RelativeMMECapacity = (uint8_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RAC STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_rac(
  LIBLTE_S1AP_RAC_STRUCT                                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - RAC
    if(LIBLTE_S1AP_RAC_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_RAC_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_rac(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RAC_STRUCT                                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - RAC
    if(LIBLTE_S1AP_RAC_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_RAC_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ReportIntervalMDT ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_reportintervalmdt(
  LIBLTE_S1AP_REPORTINTERVALMDT_ENUM                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 4);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_reportintervalmdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_REPORTINTERVALMDT_ENUM                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_REPORTINTERVALMDT_ENUM)liblte_bits_2_value(ptr, 4);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ReportArea ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_reportarea(
  LIBLTE_S1AP_REPORTAREA_ENUM_EXT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ReportArea error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_reportarea(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_REPORTAREA_ENUM_EXT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ReportArea error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_REPORTAREA_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RNC_ID INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_rnc_id(
  LIBLTE_S1AP_RNC_ID_STRUCT                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->RNC_ID
    // lb:0, ub:4095
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-12);
    liblte_value_2_bits(ie->RNC_ID, ptr, 12);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_rnc_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RNC_ID_STRUCT                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->RNC_ID
    // lb:0, ub:4095
    liblte_align_up(ptr, 8);
    ie->RNC_ID = (uint16_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RRC_Establishment_Cause ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_rrc_establishment_cause(
  LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM_EXT                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("RRC_Establishment_Cause error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_rrc_establishment_cause(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM_EXT                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("RRC_Establishment_Cause error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Routing_ID INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_routing_id(
  LIBLTE_S1AP_ROUTING_ID_STRUCT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Routing_ID
    // lb:0, ub:255
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-8);
    liblte_value_2_bits(ie->Routing_ID, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_routing_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ROUTING_ID_STRUCT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Routing_ID
    // lb:0, ub:255
    liblte_align_up(ptr, 8);
    ie->Routing_ID = (uint8_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SONInformationRequest ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_soninformationrequest(
  LIBLTE_S1AP_SONINFORMATIONREQUEST_ENUM_EXT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SONInformationRequest error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_soninformationrequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SONINFORMATIONREQUEST_ENUM_EXT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SONInformationRequest error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_SONINFORMATIONREQUEST_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Source_ToTarget_TransparentContainer DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_source_totarget_transparentcontainer(
  LIBLTE_S1AP_SOURCE_TOTARGET_TRANSPARENTCONTAINER_STRUCT            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Source-ToTarget-TransparentContainer
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_source_totarget_transparentcontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SOURCE_TOTARGET_TRANSPARENTCONTAINER_STRUCT            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Source-ToTarget-TransparentContainer
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SRVCCHOIndication ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_srvcchoindication(
  LIBLTE_S1AP_SRVCCHOINDICATION_ENUM_EXT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SRVCCHOIndication error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_srvcchoindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SRVCCHOINDICATION_ENUM_EXT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SRVCCHOIndication error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_SRVCCHOINDICATION_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SourceRNC_ToTargetRNC_TransparentContainer DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_sourcernc_totargetrnc_transparentcontainer(
  LIBLTE_S1AP_SOURCERNC_TOTARGETRNC_TRANSPARENTCONTAINER_STRUCT       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - SourceRNC-ToTargetRNC-TransparentContainer
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_sourcernc_totargetrnc_transparentcontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SOURCERNC_TOTARGETRNC_TRANSPARENTCONTAINER_STRUCT       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - SourceRNC-ToTargetRNC-TransparentContainer
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SubscriberProfileIDforRFP INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_subscriberprofileidforrfp(
  LIBLTE_S1AP_SUBSCRIBERPROFILEIDFORRFP_STRUCT                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->SubscriberProfileIDforRFP
    // lb:1, ub:256
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-8);
    liblte_value_2_bits(ie->SubscriberProfileIDforRFP, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_subscriberprofileidforrfp(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SUBSCRIBERPROFILEIDFORRFP_STRUCT                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->SubscriberProfileIDforRFP
    // lb:1, ub:256
    liblte_align_up(ptr, 8);
    ie->SubscriberProfileIDforRFP = (uint8_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SynchronizationStatus ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_synchronizationstatus(
  LIBLTE_S1AP_SYNCHRONIZATIONSTATUS_ENUM_EXT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SynchronizationStatus error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_synchronizationstatus(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SYNCHRONIZATIONSTATUS_ENUM_EXT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SynchronizationStatus error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_SYNCHRONIZATIONSTATUS_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TargetRNC_ToSourceRNC_TransparentContainer DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_targetrnc_tosourcernc_transparentcontainer(
  LIBLTE_S1AP_TARGETRNC_TOSOURCERNC_TRANSPARENTCONTAINER_STRUCT       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - TargetRNC-ToSourceRNC-TransparentContainer
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_targetrnc_tosourcernc_transparentcontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TARGETRNC_TOSOURCERNC_TRANSPARENTCONTAINER_STRUCT       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - TargetRNC-ToSourceRNC-TransparentContainer
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Threshold_RSRQ INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_threshold_rsrq(
  LIBLTE_S1AP_THRESHOLD_RSRQ_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Threshold_RSRQ
    // lb:0, ub:34
    liblte_value_2_bits(ie->Threshold_RSRQ, ptr, 6);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_threshold_rsrq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_THRESHOLD_RSRQ_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Threshold_RSRQ
    // lb:0, ub:34
    ie->Threshold_RSRQ = (uint8_t)liblte_bits_2_value(ptr, 6);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Time_UE_StayedInCell INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_time_ue_stayedincell(
  LIBLTE_S1AP_TIME_UE_STAYEDINCELL_STRUCT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Time_UE_StayedInCell
    // lb:0, ub:4095
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-12);
    liblte_value_2_bits(ie->Time_UE_StayedInCell, ptr, 12);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_time_ue_stayedincell(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TIME_UE_STAYEDINCELL_STRUCT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Time_UE_StayedInCell
    // lb:0, ub:4095
    liblte_align_up(ptr, 8);
    ie->Time_UE_StayedInCell = (uint16_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TransportLayerAddress DYNAMIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_transportlayeraddress(
  LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT                           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic bit string - TransportLayerAddress
    // lb:1, ub:160
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TransportLayerAddress error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Length
    liblte_value_2_bits(ie->n_bits-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    
    // Bits
    uint32_t i;
    for(i=0;i<ie->n_bits;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_transportlayeraddress(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT                           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic bit string - TransportLayerAddress
    // lb:1, ub:160
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TransportLayerAddress error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Length
    ie->n_bits = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);

    // Bits
    uint32_t i;
    for(i=0;i<ie->n_bits;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TraceDepth ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracedepth(
  LIBLTE_S1AP_TRACEDEPTH_ENUM_EXT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TraceDepth error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tracedepth(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TRACEDEPTH_ENUM_EXT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TraceDepth error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_TRACEDEPTH_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TrafficLoadReductionIndication INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_trafficloadreductionindication(
  LIBLTE_S1AP_TRAFFICLOADREDUCTIONINDICATION_STRUCT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->TrafficLoadReductionIndication
    // lb:1, ub:99
    liblte_value_2_bits(ie->TrafficLoadReductionIndication, ptr, 7);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_trafficloadreductionindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TRAFFICLOADREDUCTIONINDICATION_STRUCT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->TrafficLoadReductionIndication
    // lb:1, ub:99
    ie->TrafficLoadReductionIndication = (uint8_t)liblte_bits_2_value(ptr, 7);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UERadioCapability DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapability(
  LIBLTE_S1AP_UERADIOCAPABILITY_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - UERadioCapability
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ueradiocapability(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UERADIOCAPABILITY_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - UERadioCapability
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE WarningType STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_warningtype(
  LIBLTE_S1AP_WARNINGTYPE_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - WarningType
    if(LIBLTE_S1AP_WARNINGTYPE_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_WARNINGTYPE_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_warningtype(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_WARNINGTYPE_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - WarningType
    if(LIBLTE_S1AP_WARNINGTYPE_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_WARNINGTYPE_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE WarningMessageContents DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_warningmessagecontents(
  LIBLTE_S1AP_WARNINGMESSAGECONTENTS_STRUCT                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - WarningMessageContents
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_warningmessagecontents(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_WARNINGMESSAGECONTENTS_STRUCT                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - WarningMessageContents
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CauseProtocol ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_causeprotocol(
  LIBLTE_S1AP_CAUSEPROTOCOL_ENUM_EXT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseProtocol error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_causeprotocol(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CAUSEPROTOCOL_ENUM_EXT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseProtocol error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CAUSEPROTOCOL_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CellAccessMode ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellaccessmode(
  LIBLTE_S1AP_CELLACCESSMODE_ENUM_EXT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellAccessMode error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellaccessmode(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELLACCESSMODE_ENUM_EXT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellAccessMode error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CELLACCESSMODE_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000RATType ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000rattype(
  LIBLTE_S1AP_CDMA2000RATTYPE_ENUM_EXT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cdma2000RATType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000rattype(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000RATTYPE_ENUM_EXT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cdma2000RATType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CDMA2000RATTYPE_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000OneXMEID DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000onexmeid(
  LIBLTE_S1AP_CDMA2000ONEXMEID_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000OneXMEID
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000onexmeid(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000ONEXMEID_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000OneXMEID
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cell_Size ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cell_size(
  LIBLTE_S1AP_CELL_SIZE_ENUM_EXT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cell_Size error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 2);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cell_size(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELL_SIZE_ENUM_EXT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cell_Size error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CELL_SIZE_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CI STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ci(
  LIBLTE_S1AP_CI_STRUCT                                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - CI
    if(LIBLTE_S1AP_CI_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_CI_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ci(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CI_STRUCT                                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - CI
    if(LIBLTE_S1AP_CI_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_CI_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CSFallbackIndicator ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_csfallbackindicator(
  LIBLTE_S1AP_CSFALLBACKINDICATOR_ENUM_EXT                           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CSFallbackIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_csfallbackindicator(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CSFALLBACKINDICATOR_ENUM_EXT                           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CSFallbackIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CSFALLBACKINDICATOR_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CSGMembershipStatus ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_csgmembershipstatus(
  LIBLTE_S1AP_CSGMEMBERSHIPSTATUS_ENUM                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 1);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_csgmembershipstatus(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CSGMEMBERSHIPSTATUS_ENUM                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_CSGMEMBERSHIPSTATUS_ENUM)liblte_bits_2_value(ptr, 1);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE DataCodingScheme STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_datacodingscheme(
  LIBLTE_S1AP_DATACODINGSCHEME_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - DataCodingScheme
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_DATACODINGSCHEME_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_datacodingscheme(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_DATACODINGSCHEME_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - DataCodingScheme
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_DATACODINGSCHEME_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EmergencyAreaIDList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_emergencyareaidlist(
  LIBLTE_S1AP_EMERGENCYAREAIDLIST_STRUCT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("EmergencyAreaIDList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_emergencyareaid(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_emergencyareaidlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EMERGENCYAREAIDLIST_STRUCT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("EmergencyAreaIDList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_emergencyareaid(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EmergencyAreaIDListForRestart DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_emergencyareaidlistforrestart(
  LIBLTE_S1AP_EMERGENCYAREAIDLISTFORRESTART_STRUCT                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("EmergencyAreaIDListForRestart pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_emergencyareaid(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_emergencyareaidlistforrestart(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EMERGENCYAREAIDLISTFORRESTART_STRUCT                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("EmergencyAreaIDListForRestart unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_emergencyareaid(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ENB_UE_S1AP_ID INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enb_ue_s1ap_id(
  LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ENB_UE_S1AP_ID
    // lb:0, ub:16777215
    // Range > 65536 - encoded based on value
    {
      uint32_t n_bits   = floor(log2(ie->ENB_UE_S1AP_ID-0)+1);
      uint32_t n_octets = (n_bits+7)/8;
      liblte_value_2_bits(n_octets-1, ptr, 2);
      liblte_align_up_zero(ptr, 8);
      liblte_value_2_bits(0, ptr, (n_octets*8)-n_bits);
      liblte_value_2_bits(ie->ENB_UE_S1AP_ID-0, ptr, n_bits);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enb_ue_s1ap_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ENB_UE_S1AP_ID
    // lb:0, ub:16777215
    // Range > 65536 - encoded based on value
    {
      uint32_t n_octets = liblte_bits_2_value(ptr, 2) + 1;
      liblte_align_up(ptr, 8);
      ie->ENB_UE_S1AP_ID = liblte_bits_2_value(ptr, n_octets*8) + 0;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RAB_ID INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rab_id(
  LIBLTE_S1AP_E_RAB_ID_STRUCT                                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->E_RAB_ID
    // lb:0, ub:15
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ie->E_RAB_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_value_2_bits(ie->E_RAB_ID, ptr, 4);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rab_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RAB_ID_STRUCT                                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->E_RAB_ID
    // lb:0, ub:15
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ie->E_RAB_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    ie->E_RAB_ID = (uint8_t)liblte_bits_2_value(ptr, 4);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABInformationListItem SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabinformationlistitem(
  LIBLTE_S1AP_E_RABINFORMATIONLISTITEM_STRUCT                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABInformationListItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->dL_Forwarding_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->dL_Forwarding_present) {
      if(liblte_s1ap_pack_dl_forwarding(&ie->dL_Forwarding, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabinformationlistitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABINFORMATIONLISTITEM_STRUCT                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABInformationListItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->dL_Forwarding_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->dL_Forwarding_present) {
      if(liblte_s1ap_unpack_dl_forwarding(ptr, &ie->dL_Forwarding) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EUTRANRoundTripDelayEstimationInfo INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_eutranroundtripdelayestimationinfo(
  LIBLTE_S1AP_EUTRANROUNDTRIPDELAYESTIMATIONINFO_STRUCT              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->EUTRANRoundTripDelayEstimationInfo
    // lb:0, ub:2047
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-11);
    liblte_value_2_bits(ie->EUTRANRoundTripDelayEstimationInfo, ptr, 11);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_eutranroundtripdelayestimationinfo(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EUTRANROUNDTRIPDELAYESTIMATIONINFO_STRUCT              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->EUTRANRoundTripDelayEstimationInfo
    // lb:0, ub:2047
    liblte_align_up(ptr, 8);
    ie->EUTRANRoundTripDelayEstimationInfo = (uint16_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ForbiddenLACs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:4096
LIBLTE_ERROR_ENUM liblte_s1ap_pack_forbiddenlacs(
  LIBLTE_S1AP_FORBIDDENLACS_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ForbiddenLACs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 12);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_lac(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_forbiddenlacs(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_FORBIDDENLACS_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 12) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ForbiddenLACs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_lac(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE GTP_TEID STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_gtp_teid(
  LIBLTE_S1AP_GTP_TEID_STRUCT                                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - GTP-TEID
    if(LIBLTE_S1AP_GTP_TEID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_GTP_TEID_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_gtp_teid(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_GTP_TEID_STRUCT                                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - GTP-TEID
    if(LIBLTE_S1AP_GTP_TEID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_GTP_TEID_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE GUMMEIType ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_gummeitype(
  LIBLTE_S1AP_GUMMEITYPE_ENUM_EXT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("GUMMEIType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_gummeitype(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_GUMMEITYPE_ENUM_EXT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("GUMMEIType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_GUMMEITYPE_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE HandoverType ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovertype(
  LIBLTE_S1AP_HANDOVERTYPE_ENUM_EXT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("HandoverType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handovertype(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_HANDOVERTYPE_ENUM_EXT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("HandoverType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_HANDOVERTYPE_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE IntegrityProtectionAlgorithms STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_integrityprotectionalgorithms(
  LIBLTE_S1AP_INTEGRITYPROTECTIONALGORITHMS_STRUCT                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - IntegrityProtectionAlgorithms
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("IntegrityProtectionAlgorithms error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_INTEGRITYPROTECTIONALGORITHMS_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_integrityprotectionalgorithms(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_INTEGRITYPROTECTIONALGORITHMS_STRUCT                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - IntegrityProtectionAlgorithms
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("IntegrityProtectionAlgorithms error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_INTEGRITYPROTECTIONALGORITHMS_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LastVisitedGERANCellInformation CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lastvisitedgerancellinformation(
  LIBLTE_S1AP_LASTVISITEDGERANCELLINFORMATION_STRUCT                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("LastVisitedGERANCellInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 0);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_LASTVISITEDGERANCELLINFORMATION_CHOICE_UNDEFINED) {
      } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lastvisitedgerancellinformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LASTVISITEDGERANCELLINFORMATION_STRUCT                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("LastVisitedGERANCellInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_LASTVISITEDGERANCELLINFORMATION_CHOICE_ENUM)liblte_bits_2_value(ptr, 0);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_LASTVISITEDGERANCELLINFORMATION_CHOICE_UNDEFINED) {
      } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Links_to_log ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_links_to_log(
  LIBLTE_S1AP_LINKS_TO_LOG_ENUM_EXT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Links_to_log error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 2);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_links_to_log(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LINKS_TO_LOG_ENUM_EXT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Links_to_log error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_LINKS_TO_LOG_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LoggingInterval ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_logginginterval(
  LIBLTE_S1AP_LOGGINGINTERVAL_ENUM                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 3);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_logginginterval(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LOGGINGINTERVAL_ENUM                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_LOGGINGINTERVAL_ENUM)liblte_bits_2_value(ptr, 3);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M3period ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m3period(
  LIBLTE_S1AP_M3PERIOD_ENUM_EXT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("M3period error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 2);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m3period(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M3PERIOD_ENUM_EXT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("M3period error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_M3PERIOD_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M4period ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m4period(
  LIBLTE_S1AP_M4PERIOD_ENUM_EXT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("M4period error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m4period(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M4PERIOD_ENUM_EXT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("M4period error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_M4PERIOD_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M5period ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m5period(
  LIBLTE_S1AP_M5PERIOD_ENUM_EXT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("M5period error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m5period(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M5PERIOD_ENUM_EXT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("M5period error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_M5PERIOD_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MobilityInformation STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mobilityinformation(
  LIBLTE_S1AP_MOBILITYINFORMATION_STRUCT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - MobilityInformation
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MOBILITYINFORMATION_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mobilityinformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MOBILITYINFORMATION_STRUCT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - MobilityInformation
    liblte_align_up(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MOBILITYINFORMATION_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MME_Code STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mme_code(
  LIBLTE_S1AP_MME_CODE_STRUCT                                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - MME-Code
    if(LIBLTE_S1AP_MME_CODE_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MME_CODE_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mme_code(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MME_CODE_STRUCT                                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - MME-Code
    if(LIBLTE_S1AP_MME_CODE_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MME_CODE_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MSClassmark3 DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_msclassmark3(
  LIBLTE_S1AP_MSCLASSMARK3_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - MSClassmark3
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_msclassmark3(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MSCLASSMARK3_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - MSClassmark3
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE NumberofBroadcastRequest INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_numberofbroadcastrequest(
  LIBLTE_S1AP_NUMBEROFBROADCASTREQUEST_STRUCT                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->NumberofBroadcastRequest
    // lb:0, ub:65535
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (2*8)-16);
    liblte_value_2_bits(ie->NumberofBroadcastRequest, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_numberofbroadcastrequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_NUMBEROFBROADCASTREQUEST_STRUCT                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->NumberofBroadcastRequest
    // lb:0, ub:65535
    liblte_align_up(ptr, 8);
    ie->NumberofBroadcastRequest = (uint16_t)liblte_bits_2_value(ptr, 2.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE OverloadResponse CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadresponse(
  LIBLTE_S1AP_OVERLOADRESPONSE_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("OverloadResponse error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 0);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_OVERLOADRESPONSE_CHOICE_OVERLOADACTION) {
      if(liblte_s1ap_pack_overloadaction(&ie->choice.overloadAction, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_overloadresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_OVERLOADRESPONSE_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("OverloadResponse error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_OVERLOADRESPONSE_CHOICE_ENUM)liblte_bits_2_value(ptr, 0);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_OVERLOADRESPONSE_CHOICE_OVERLOADACTION) {
      if(liblte_s1ap_unpack_overloadaction(ptr, &ie->choice.overloadAction) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PDCP_SNExtended INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pdcp_snextended(
  LIBLTE_S1AP_PDCP_SNEXTENDED_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->PDCP_SNExtended
    // lb:0, ub:32767
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-15);
    liblte_value_2_bits(ie->PDCP_SNExtended, ptr, 15);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pdcp_snextended(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PDCP_SNEXTENDED_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->PDCP_SNExtended
    // lb:0, ub:32767
    liblte_align_up(ptr, 8);
    ie->PDCP_SNExtended = (uint16_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Pre_emptionCapability ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pre_emptioncapability(
  LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_ENUM                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 1);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pre_emptioncapability(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_ENUM                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_ENUM)liblte_bits_2_value(ptr, 1);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE QCI INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_qci(
  LIBLTE_S1AP_QCI_STRUCT                                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->QCI
    // lb:0, ub:255
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-8);
    liblte_value_2_bits(ie->QCI, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_qci(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_QCI_STRUCT                                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->QCI
    // lb:0, ub:255
    liblte_align_up(ptr, 8);
    ie->QCI = (uint8_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RelayNode_Indicator ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_relaynode_indicator(
  LIBLTE_S1AP_RELAYNODE_INDICATOR_ENUM_EXT                           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("RelayNode_Indicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_relaynode_indicator(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RELAYNODE_INDICATOR_ENUM_EXT                           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("RelayNode_Indicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_RELAYNODE_INDICATOR_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M1ReportingTrigger ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m1reportingtrigger(
  LIBLTE_S1AP_M1REPORTINGTRIGGER_ENUM_EXT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("M1ReportingTrigger error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 2);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m1reportingtrigger(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M1REPORTINGTRIGGER_ENUM_EXT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("M1ReportingTrigger error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_M1REPORTINGTRIGGER_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RIMInformation DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_riminformation(
  LIBLTE_S1AP_RIMINFORMATION_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - RIMInformation
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_riminformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RIMINFORMATION_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - RIMInformation
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RepetitionPeriod INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_repetitionperiod(
  LIBLTE_S1AP_REPETITIONPERIOD_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->RepetitionPeriod
    // lb:0, ub:4095
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (1*8)-12);
    liblte_value_2_bits(ie->RepetitionPeriod, ptr, 12);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_repetitionperiod(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_REPETITIONPERIOD_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->RepetitionPeriod
    // lb:0, ub:4095
    liblte_align_up(ptr, 8);
    ie->RepetitionPeriod = (uint16_t)liblte_bits_2_value(ptr, 1.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SecurityKey STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_securitykey(
  LIBLTE_S1AP_SECURITYKEY_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - SecurityKey
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_SECURITYKEY_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_securitykey(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SECURITYKEY_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - SecurityKey
    liblte_align_up(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_SECURITYKEY_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SerialNumber STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_serialnumber(
  LIBLTE_S1AP_SERIALNUMBER_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - SerialNumber
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_SERIALNUMBER_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_serialnumber(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SERIALNUMBER_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - SerialNumber
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_SERIALNUMBER_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SourceBSS_ToTargetBSS_TransparentContainer DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_sourcebss_totargetbss_transparentcontainer(
  LIBLTE_S1AP_SOURCEBSS_TOTARGETBSS_TRANSPARENTCONTAINER_STRUCT       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - SourceBSS-ToTargetBSS-TransparentContainer
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_sourcebss_totargetbss_transparentcontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SOURCEBSS_TOTARGETBSS_TRANSPARENTCONTAINER_STRUCT       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - SourceBSS-ToTargetBSS-TransparentContainer
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SRVCCOperationPossible ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_srvccoperationpossible(
  LIBLTE_S1AP_SRVCCOPERATIONPOSSIBLE_ENUM_EXT                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SRVCCOperationPossible error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_srvccoperationpossible(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SRVCCOPERATIONPOSSIBLE_ENUM_EXT                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SRVCCOperationPossible error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_SRVCCOPERATIONPOSSIBLE_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ServedGroupIDs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_servedgroupids(
  LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ServedGroupIDs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_mme_group_id(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_servedgroupids(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ServedGroupIDs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_mme_group_id(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE StratumLevel INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_stratumlevel(
  LIBLTE_S1AP_STRATUMLEVEL_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->StratumLevel
    // lb:0, ub:3
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ie->StratumLevel error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_value_2_bits(ie->StratumLevel, ptr, 2);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_stratumlevel(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_STRATUMLEVEL_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->StratumLevel
    // lb:0, ub:3
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ie->StratumLevel error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    ie->StratumLevel = (uint8_t)liblte_bits_2_value(ptr, 2);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAC STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tac(
  LIBLTE_S1AP_TAC_STRUCT                                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - TAC
    if(LIBLTE_S1AP_TAC_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_TAC_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tac(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAC_STRUCT                                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - TAC
    if(LIBLTE_S1AP_TAC_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_TAC_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAListforMDT DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:8
LIBLTE_ERROR_ENUM liblte_s1ap_pack_talistformdt(
  LIBLTE_S1AP_TALISTFORMDT_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("TAListforMDT pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tac(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_talistformdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TALISTFORMDT_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 3) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("TAListforMDT unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tac(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TBCD_STRING STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tbcd_string(
  LIBLTE_S1AP_TBCD_STRING_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - TBCD-STRING
    if(LIBLTE_S1AP_TBCD_STRING_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_TBCD_STRING_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tbcd_string(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TBCD_STRING_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - TBCD-STRING
    if(LIBLTE_S1AP_TBCD_STRING_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_TBCD_STRING_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Target_ToSource_TransparentContainer DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_target_tosource_transparentcontainer(
  LIBLTE_S1AP_TARGET_TOSOURCE_TRANSPARENTCONTAINER_STRUCT            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Target-ToSource-TransparentContainer
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_target_tosource_transparentcontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TARGET_TOSOURCE_TRANSPARENTCONTAINER_STRUCT            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Target-ToSource-TransparentContainer
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Threshold_RSRP INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_threshold_rsrp(
  LIBLTE_S1AP_THRESHOLD_RSRP_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Threshold_RSRP
    // lb:0, ub:97
    liblte_value_2_bits(ie->Threshold_RSRP, ptr, 7);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_threshold_rsrp(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_THRESHOLD_RSRP_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Threshold_RSRP
    // lb:0, ub:97
    ie->Threshold_RSRP = (uint8_t)liblte_bits_2_value(ptr, 7);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Time_UE_StayedInCell_EnhancedGranularity INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_time_ue_stayedincell_enhancedgranularity(
  LIBLTE_S1AP_TIME_UE_STAYEDINCELL_ENHANCEDGRANULARITY_STRUCT        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Time_UE_StayedInCell_EnhancedGranularity
    // lb:0, ub:40950
    liblte_align_up_zero(ptr, 8);
    liblte_value_2_bits(0, ptr, (2*8)-16);
    liblte_value_2_bits(ie->Time_UE_StayedInCell_EnhancedGranularity, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_time_ue_stayedincell_enhancedgranularity(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TIME_UE_STAYEDINCELL_ENHANCEDGRANULARITY_STRUCT        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->Time_UE_StayedInCell_EnhancedGranularity
    // lb:0, ub:40950
    liblte_align_up(ptr, 8);
    ie->Time_UE_StayedInCell_EnhancedGranularity = (uint16_t)liblte_bits_2_value(ptr, 2.0*8);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_UTRAN_Trace_ID STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_utran_trace_id(
  LIBLTE_S1AP_E_UTRAN_TRACE_ID_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - E-UTRAN-Trace-ID
    if(LIBLTE_S1AP_E_UTRAN_TRACE_ID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_E_UTRAN_TRACE_ID_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_utran_trace_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_UTRAN_TRACE_ID_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - E-UTRAN-Trace-ID
    if(LIBLTE_S1AP_E_UTRAN_TRACE_ID_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_E_UTRAN_TRACE_ID_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TypeOfError ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_typeoferror(
  LIBLTE_S1AP_TYPEOFERROR_ENUM_EXT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TypeOfError error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_typeoferror(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TYPEOFERROR_ENUM_EXT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TypeOfError error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_TYPEOFERROR_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UEAggregateMaximumBitrate SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueaggregatemaximumbitrate(
  LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("UEAggregateMaximumBitrate error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_bitrate(&ie->uEaggregateMaximumBitRateDL, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_bitrate(&ie->uEaggregateMaximumBitRateUL, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ueaggregatemaximumbitrate(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("UEAggregateMaximumBitrate error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_bitrate(ptr, &ie->uEaggregateMaximumBitRateDL) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_bitrate(ptr, &ie->uEaggregateMaximumBitRateUL) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UE_S1AP_ID_pair SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_s1ap_id_pair(
  LIBLTE_S1AP_UE_S1AP_ID_PAIR_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("UE_S1AP_ID_pair error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_mme_ue_s1ap_id(&ie->mME_UE_S1AP_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_enb_ue_s1ap_id(&ie->eNB_UE_S1AP_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_s1ap_id_pair(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UE_S1AP_ID_PAIR_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("UE_S1AP_ID_pair error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &ie->mME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &ie->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UEIdentityIndexValue STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueidentityindexvalue(
  LIBLTE_S1AP_UEIDENTITYINDEXVALUE_STRUCT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - UEIdentityIndexValue
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_UEIDENTITYINDEXVALUE_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ueidentityindexvalue(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UEIDENTITYINDEXVALUE_STRUCT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - UEIdentityIndexValue
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_UEIDENTITYINDEXVALUE_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UESecurityCapabilities SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uesecuritycapabilities(
  LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("UESecurityCapabilities error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_encryptionalgorithms(&ie->encryptionAlgorithms, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_integrityprotectionalgorithms(&ie->integrityProtectionAlgorithms, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uesecuritycapabilities(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("UESecurityCapabilities error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_encryptionalgorithms(ptr, &ie->encryptionAlgorithms) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_integrityprotectionalgorithms(ptr, &ie->integrityProtectionAlgorithms) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE VoiceSupportMatchIndicator ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_voicesupportmatchindicator(
  LIBLTE_S1AP_VOICESUPPORTMATCHINDICATOR_ENUM_EXT                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("VoiceSupportMatchIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_voicesupportmatchindicator(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_VOICESUPPORTMATCHINDICATOR_ENUM_EXT                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("VoiceSupportMatchIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_VOICESUPPORTMATCHINDICATOR_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE WarningSecurityInfo STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_warningsecurityinfo(
  LIBLTE_S1AP_WARNINGSECURITYINFO_STRUCT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - WarningSecurityInfo
    if(LIBLTE_S1AP_WARNINGSECURITYINFO_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_WARNINGSECURITYINFO_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_warningsecurityinfo(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_WARNINGSECURITYINFO_STRUCT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - WarningSecurityInfo
    if(LIBLTE_S1AP_WARNINGSECURITYINFO_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_WARNINGSECURITYINFO_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ENBX2GTPTLAs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:16
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbx2gtptlas(
  LIBLTE_S1AP_ENBX2GTPTLAS_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ENBX2GTPTLAs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 4);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_transportlayeraddress(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbx2gtptlas(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ENBX2GTPTLAS_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 4) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ENBX2GTPTLAs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CauseTransport ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_causetransport(
  LIBLTE_S1AP_CAUSETRANSPORT_ENUM_EXT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseTransport error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_causetransport(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CAUSETRANSPORT_ENUM_EXT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CauseTransport error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CAUSETRANSPORT_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000HOStatus ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000hostatus(
  LIBLTE_S1AP_CDMA2000HOSTATUS_ENUM_EXT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cdma2000HOStatus error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000hostatus(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000HOSTATUS_ENUM_EXT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cdma2000HOStatus error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_CDMA2000HOSTATUS_ENUM)liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000OneXPilot DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000onexpilot(
  LIBLTE_S1AP_CDMA2000ONEXPILOT_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000OneXPilot
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000onexpilot(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000ONEXPILOT_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - Cdma2000OneXPilot
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ConcurrentWarningMessageIndicator ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_concurrentwarningmessageindicator(
  LIBLTE_S1AP_CONCURRENTWARNINGMESSAGEINDICATOR_ENUM                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 0);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_concurrentwarningmessageindicator(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CONCURRENTWARNINGMESSAGEINDICATOR_ENUM                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_CONCURRENTWARNINGMESSAGEINDICATOR_ENUM)liblte_bits_2_value(ptr, 0);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE COUNTvalue SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_countvalue(
  LIBLTE_S1AP_COUNTVALUE_STRUCT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("COUNTvalue error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_pdcp_sn(&ie->pDCP_SN, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_hfn(&ie->hFN, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_countvalue(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_COUNTVALUE_STRUCT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("COUNTvalue error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_pdcp_sn(ptr, &ie->pDCP_SN) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_hfn(ptr, &ie->hFN) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CriticalityDiagnostics_IE_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_criticalitydiagnostics_ie_item(
  LIBLTE_S1AP_CRITICALITYDIAGNOSTICS_IE_ITEM_STRUCT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CriticalityDiagnostics_IE_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    // Enum - ie->iECriticality
    liblte_value_2_bits(ie->iECriticality, ptr, 2);

    if(liblte_s1ap_pack_protocolie_id(&ie->iE_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_typeoferror(&ie->typeOfError, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_criticalitydiagnostics_ie_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CRITICALITYDIAGNOSTICS_IE_ITEM_STRUCT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CriticalityDiagnostics_IE_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    // Enum - ie->iECriticality
    ie->iECriticality = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);

    if(liblte_s1ap_unpack_protocolie_id(ptr, &ie->iE_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_typeoferror(ptr, &ie->typeOfError) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ENBX2TLAs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:2
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbx2tlas(
  LIBLTE_S1AP_ENBX2TLAS_STRUCT                                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ENBX2TLAs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_transportlayeraddress(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbx2tlas(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ENBX2TLAS_STRUCT                                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 0) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ENBX2TLAs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ExtendedRepetitionPeriod INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_extendedrepetitionperiod(
  LIBLTE_S1AP_EXTENDEDREPETITIONPERIOD_STRUCT                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ExtendedRepetitionPeriod
    // lb:4096, ub:131071
    // Range > 65536 - encoded based on value
    {
      uint32_t n_bits   = floor(log2(ie->ExtendedRepetitionPeriod-4096)+1);
      uint32_t n_octets = (n_bits+7)/8;
      liblte_value_2_bits(n_octets-1, ptr, 2);
      liblte_align_up_zero(ptr, 8);
      liblte_value_2_bits(0, ptr, (n_octets*8)-n_bits);
      liblte_value_2_bits(ie->ExtendedRepetitionPeriod-4096, ptr, n_bits);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_extendedrepetitionperiod(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EXTENDEDREPETITIONPERIOD_STRUCT                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->ExtendedRepetitionPeriod
    // lb:4096, ub:131071
    // Range > 65536 - encoded based on value
    {
      uint32_t n_octets = liblte_bits_2_value(ptr, 2) + 1;
      liblte_align_up(ptr, 8);
      ie->ExtendedRepetitionPeriod = liblte_bits_2_value(ptr, n_octets*8) + 4096;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ForbiddenTACs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:4096
LIBLTE_ERROR_ENUM liblte_s1ap_pack_forbiddentacs(
  LIBLTE_S1AP_FORBIDDENTACS_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ForbiddenTACs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 12);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tac(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_forbiddentacs(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_FORBIDDENTACS_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 12) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ForbiddenTACs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tac(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE GBR_QosInformation SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_gbr_qosinformation(
  LIBLTE_S1AP_GBR_QOSINFORMATION_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("GBR_QosInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_bitrate(&ie->e_RAB_MaximumBitrateDL, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_bitrate(&ie->e_RAB_MaximumBitrateUL, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_bitrate(&ie->e_RAB_GuaranteedBitrateDL, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_bitrate(&ie->e_RAB_GuaranteedBitrateUL, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_gbr_qosinformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_GBR_QOSINFORMATION_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("GBR_QosInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_bitrate(ptr, &ie->e_RAB_MaximumBitrateDL) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_bitrate(ptr, &ie->e_RAB_MaximumBitrateUL) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_bitrate(ptr, &ie->e_RAB_GuaranteedBitrateDL) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_bitrate(ptr, &ie->e_RAB_GuaranteedBitrateUL) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE HFNModified INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_hfnmodified(
  LIBLTE_S1AP_HFNMODIFIED_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->HFNModified
    // lb:0, ub:131071
    // Range > 65536 - encoded based on value
    {
      uint32_t n_bits   = floor(log2(ie->HFNModified-0)+1);
      uint32_t n_octets = (n_bits+7)/8;
      liblte_value_2_bits(n_octets-1, ptr, 2);
      liblte_align_up_zero(ptr, 8);
      liblte_value_2_bits(0, ptr, (n_octets*8)-n_bits);
      liblte_value_2_bits(ie->HFNModified-0, ptr, n_bits);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_hfnmodified(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_HFNMODIFIED_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->HFNModified
    // lb:0, ub:131071
    // Range > 65536 - encoded based on value
    {
      uint32_t n_octets = liblte_bits_2_value(ptr, 2) + 1;
      liblte_align_up(ptr, 8);
      ie->HFNModified = liblte_bits_2_value(ptr, n_octets*8) + 0;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE KillAllWarningMessages ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_killallwarningmessages(
  LIBLTE_S1AP_KILLALLWARNINGMESSAGES_ENUM                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 0);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_killallwarningmessages(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_KILLALLWARNINGMESSAGES_ENUM                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_KILLALLWARNINGMESSAGES_ENUM)liblte_bits_2_value(ptr, 0);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LPPa_PDU DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lppa_pdu(
  LIBLTE_S1AP_LPPA_PDU_STRUCT                                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - LPPa-PDU
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lppa_pdu(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LPPA_PDU_STRUCT                                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - LPPa-PDU
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M3Configuration SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m3configuration(
  LIBLTE_S1AP_M3CONFIGURATION_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("M3Configuration error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_m3period(&ie->m3period, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m3configuration(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M3CONFIGURATION_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("M3Configuration error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_m3period(ptr, &ie->m3period) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M5Configuration SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m5configuration(
  LIBLTE_S1AP_M5CONFIGURATION_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("M5Configuration error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_m5period(&ie->m5period, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_links_to_log(&ie->m5_links_to_log, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m5configuration(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M5CONFIGURATION_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("M5Configuration error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_m5period(ptr, &ie->m5period) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_links_to_log(ptr, &ie->m5_links_to_log) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MeasurementThresholdA2 CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_measurementthresholda2(
  LIBLTE_S1AP_MEASUREMENTTHRESHOLDA2_STRUCT                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("MeasurementThresholdA2 error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_MEASUREMENTTHRESHOLDA2_CHOICE_THRESHOLD_RSRP) {
      if(liblte_s1ap_pack_threshold_rsrp(&ie->choice.threshold_RSRP, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_MEASUREMENTTHRESHOLDA2_CHOICE_THRESHOLD_RSRQ) {
      if(liblte_s1ap_pack_threshold_rsrq(&ie->choice.threshold_RSRQ, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_measurementthresholda2(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MEASUREMENTTHRESHOLDA2_STRUCT                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("MeasurementThresholdA2 error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_MEASUREMENTTHRESHOLDA2_CHOICE_ENUM)liblte_bits_2_value(ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_MEASUREMENTTHRESHOLDA2_CHOICE_THRESHOLD_RSRP) {
      if(liblte_s1ap_unpack_threshold_rsrp(ptr, &ie->choice.threshold_RSRP) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_MEASUREMENTTHRESHOLDA2_CHOICE_THRESHOLD_RSRQ) {
      if(liblte_s1ap_unpack_threshold_rsrq(ptr, &ie->choice.threshold_RSRQ) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M_TMSI STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m_tmsi(
  LIBLTE_S1AP_M_TMSI_STRUCT                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - M-TMSI
    if(LIBLTE_S1AP_M_TMSI_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_M_TMSI_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m_tmsi(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M_TMSI_STRUCT                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - M-TMSI
    if(LIBLTE_S1AP_M_TMSI_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_M_TMSI_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE OldBSS_ToNewBSS_Information DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_oldbss_tonewbss_information(
  LIBLTE_S1AP_OLDBSS_TONEWBSS_INFORMATION_STRUCT                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - OldBSS-ToNewBSS-Information
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_oldbss_tonewbss_information(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_OLDBSS_TONEWBSS_INFORMATION_STRUCT                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - OldBSS-ToNewBSS-Information
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PLMNidentity STATIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_plmnidentity(
  LIBLTE_S1AP_PLMNIDENTITY_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - PLMNidentity
    if(LIBLTE_S1AP_PLMNIDENTITY_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up_zero(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_PLMNIDENTITY_OCTET_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_plmnidentity(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PLMNIDENTITY_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static octet string - PLMNidentity
    if(LIBLTE_S1AP_PLMNIDENTITY_OCTET_STRING_LEN > 2) { // X.691 Sec.16
      liblte_align_up(ptr, 8);
    }
    // Octets
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_PLMNIDENTITY_OCTET_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ReceiveStatusOfULPDCPSDUsExtended DYNAMIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_receivestatusofulpdcpsdusextended(
  LIBLTE_S1AP_RECEIVESTATUSOFULPDCPSDUSEXTENDED_STRUCT               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic bit string - ReceiveStatusOfULPDCPSDUsExtended
    // lb:1, ub:16384
    // Length
    liblte_value_2_bits(ie->n_bits-1, ptr, 14);
    liblte_align_up_zero(ptr, 8);
    
    // Bits
    uint32_t i;
    for(i=0;i<ie->n_bits;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_receivestatusofulpdcpsdusextended(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RECEIVESTATUSOFULPDCPSDUSEXTENDED_STRUCT               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic bit string - ReceiveStatusOfULPDCPSDUsExtended
    // lb:1, ub:16384
    // Length
    ie->n_bits = liblte_bits_2_value(ptr, 14) + 1;
    liblte_align_up(ptr, 8);

    // Bits
    uint32_t i;
    for(i=0;i<ie->n_bits;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RequestType SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_requesttype(
  LIBLTE_S1AP_REQUESTTYPE_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("RequestType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_eventtype(&ie->eventType, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_reportarea(&ie->reportArea, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_requesttype(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_REQUESTTYPE_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("RequestType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_eventtype(ptr, &ie->eventType) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_reportarea(ptr, &ie->reportArea) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RRC_Container DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_rrc_container(
  LIBLTE_S1AP_RRC_CONTAINER_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - RRC-Container
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_rrc_container(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RRC_CONTAINER_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - RRC-Container
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}


/*******************************************************************************
/* ProtocolIE nextHopChainingCount INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_nexthopchainingcount(
  LIBLTE_S1AP_NEXTHOPCHAININGCOUNT_STRUCT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->nextHopChainingCount
    // lb:0, ub:7
    liblte_value_2_bits(ie->nextHopChainingCount, ptr, 3);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_nexthopchainingcount(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_NEXTHOPCHAININGCOUNT_STRUCT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->nextHopChainingCount
    // lb:0, ub:7
    ie->nextHopChainingCount = (uint8_t)liblte_bits_2_value(ptr, 3);
    err = LIBLTE_SUCCESS;
  }
  return err;
}


/*******************************************************************************
/* ProtocolIE SecurityContext SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_securitycontext(
  LIBLTE_S1AP_SECURITYCONTEXT_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SecurityContext error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_nexthopchainingcount(&ie->nextHopChainingCount, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_securitykey(&ie->nextHopParameter, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_securitycontext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SECURITYCONTEXT_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SecurityContext error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_nexthopchainingcount(ptr, &ie->nextHopChainingCount) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_securitykey(ptr, &ie->nextHopParameter) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ServedMMECs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_servedmmecs(
  LIBLTE_S1AP_SERVEDMMECS_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ServedMMECs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_mme_code(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_servedmmecs(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SERVEDMMECS_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ServedMMECs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_mme_code(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TimeSynchronizationInfo SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_timesynchronizationinfo(
  LIBLTE_S1AP_TIMESYNCHRONIZATIONINFO_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TimeSynchronizationInfo error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_stratumlevel(&ie->stratumLevel, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_synchronizationstatus(&ie->synchronizationStatus, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_timesynchronizationinfo(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TIMESYNCHRONIZATIONINFO_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TimeSynchronizationInfo error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_stratumlevel(ptr, &ie->stratumLevel) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_synchronizationstatus(ptr, &ie->synchronizationStatus) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAI SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tai(
  LIBLTE_S1AP_TAI_STRUCT                                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tbcd_string(&ie->pLMNidentity, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_tac(&ie->tAC, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tai(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAI_STRUCT                                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->pLMNidentity) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_tac(ptr, &ie->tAC) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TABasedMDT SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tabasedmdt(
  LIBLTE_S1AP_TABASEDMDT_STRUCT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TABasedMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_talistformdt(&ie->tAListforMDT, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tabasedmdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TABASEDMDT_STRUCT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TABasedMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_talistformdt(ptr, &ie->tAListforMDT) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TargeteNB_ToSourceeNB_TransparentContainer SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_targetenb_tosourceenb_transparentcontainer(
  LIBLTE_S1AP_TARGETENB_TOSOURCEENB_TRANSPARENTCONTAINER_STRUCT       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TargeteNB_ToSourceeNB_TransparentContainer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_rrc_container(&ie->rRC_Container, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_targetenb_tosourceenb_transparentcontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TARGETENB_TOSOURCEENB_TRANSPARENTCONTAINER_STRUCT       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TargeteNB_ToSourceeNB_TransparentContainer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_rrc_container(ptr, &ie->rRC_Container) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M1ThresholdEventA2 SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m1thresholdeventa2(
  LIBLTE_S1AP_M1THRESHOLDEVENTA2_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("M1ThresholdEventA2 error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_measurementthresholda2(&ie->measurementThreshold, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m1thresholdeventa2(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M1THRESHOLDEVENTA2_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("M1ThresholdEventA2 error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_measurementthresholda2(ptr, &ie->measurementThreshold) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TransportInformation SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_transportinformation(
  LIBLTE_S1AP_TRANSPORTINFORMATION_STRUCT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TransportInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }


    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_gtp_teid(&ie->uL_GTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_transportinformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TRANSPORTINFORMATION_STRUCT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TransportInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }


    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->uL_GTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TunnelInformation SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tunnelinformation(
  LIBLTE_S1AP_TUNNELINFORMATION_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TunnelInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->uDP_Port_Number_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->uDP_Port_Number_present) {
      if(liblte_s1ap_pack_port_number(&ie->uDP_Port_Number, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tunnelinformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TUNNELINFORMATION_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TunnelInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->uDP_Port_Number_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->uDP_Port_Number_present) {
      if(liblte_s1ap_unpack_port_number(ptr, &ie->uDP_Port_Number) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UE_S1AP_IDs CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_s1ap_ids(
  LIBLTE_S1AP_UE_S1AP_IDS_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("UE_S1AP_IDs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_UE_S1AP_ID_PAIR) {
      if(liblte_s1ap_pack_ue_s1ap_id_pair(&ie->choice.uE_S1AP_ID_pair, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_MME_UE_S1AP_ID) {
      if(liblte_s1ap_pack_mme_ue_s1ap_id(&ie->choice.mME_UE_S1AP_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_s1ap_ids(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UE_S1AP_IDS_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("UE_S1AP_IDs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_ENUM)liblte_bits_2_value(ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_UE_S1AP_ID_PAIR) {
      if(liblte_s1ap_unpack_ue_s1ap_id_pair(ptr, &ie->choice.uE_S1AP_ID_pair) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_MME_UE_S1AP_ID) {
      if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &ie->choice.mME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ENBX2ExtTLA SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbx2exttla(
  LIBLTE_S1AP_ENBX2EXTTLA_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ENBX2ExtTLA error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iPsecTLA_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->gTPTLAa_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(ie->iPsecTLA_present) {
      if(liblte_s1ap_pack_transportlayeraddress(&ie->iPsecTLA, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->gTPTLAa_present) {
      if(liblte_s1ap_pack_enbx2gtptlas(&ie->gTPTLAa, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbx2exttla(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ENBX2EXTTLA_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ENBX2ExtTLA error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iPsecTLA_present = liblte_bits_2_value(ptr, 1);
    ie->gTPTLAa_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(ie->iPsecTLA_present) {
      if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->iPsecTLA) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->gTPTLAa_present) {
      if(liblte_s1ap_unpack_enbx2gtptlas(ptr, &ie->gTPTLAa) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE BPLMNs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:6
LIBLTE_ERROR_ENUM liblte_s1ap_pack_bplmns(
  LIBLTE_S1AP_BPLMNS_STRUCT                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("BPLMNs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tbcd_string(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_bplmns(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_BPLMNS_STRUCT                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 3) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("BPLMNs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cause CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cause(
  LIBLTE_S1AP_CAUSE_STRUCT                                           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cause error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 3);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK) {
      if(liblte_s1ap_pack_causeradionetwork(&ie->choice.radioNetwork, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_TRANSPORT) {
      if(liblte_s1ap_pack_causetransport(&ie->choice.transport, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_NAS) {
      if(liblte_s1ap_pack_causenas(&ie->choice.nas, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_PROTOCOL) {
      if(liblte_s1ap_pack_causeprotocol(&ie->choice.protocol, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_MISC) {
      if(liblte_s1ap_pack_causemisc(&ie->choice.misc, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cause(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CAUSE_STRUCT                                           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cause error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_CAUSE_CHOICE_ENUM)liblte_bits_2_value(ptr, 3);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK) {
      if(liblte_s1ap_unpack_causeradionetwork(ptr, &ie->choice.radioNetwork) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_TRANSPORT) {
      if(liblte_s1ap_unpack_causetransport(ptr, &ie->choice.transport) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_NAS) {
      if(liblte_s1ap_unpack_causenas(ptr, &ie->choice.nas) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_PROTOCOL) {
      if(liblte_s1ap_unpack_causeprotocol(ptr, &ie->choice.protocol) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_CAUSE_CHOICE_MISC) {
      if(liblte_s1ap_unpack_causemisc(ptr, &ie->choice.misc) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Cdma2000OneXSRVCCInfo SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000onexsrvccinfo(
  LIBLTE_S1AP_CDMA2000ONEXSRVCCINFO_STRUCT                           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cdma2000OneXSRVCCInfo error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_cdma2000onexmeid(&ie->cdma2000OneXMEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_cdma2000onexmsi(&ie->cdma2000OneXMSI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_cdma2000onexpilot(&ie->cdma2000OneXPilot, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000onexsrvccinfo(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CDMA2000ONEXSRVCCINFO_STRUCT                           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Cdma2000OneXSRVCCInfo error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_cdma2000onexmeid(ptr, &ie->cdma2000OneXMEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_cdma2000onexmsi(ptr, &ie->cdma2000OneXMSI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_cdma2000onexpilot(ptr, &ie->cdma2000OneXPilot) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CGI SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cgi(
  LIBLTE_S1AP_CGI_STRUCT                                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CGI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->rAC_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tbcd_string(&ie->pLMNidentity, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_lac(&ie->lAC, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_ci(&ie->cI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->rAC_present) {
      if(liblte_s1ap_pack_rac(&ie->rAC, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cgi(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CGI_STRUCT                                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CGI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->rAC_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->pLMNidentity) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_lac(ptr, &ie->lAC) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_ci(ptr, &ie->cI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->rAC_present) {
      if(liblte_s1ap_unpack_rac(ptr, &ie->rAC) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE COUNTValueExtended SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_countvalueextended(
  LIBLTE_S1AP_COUNTVALUEEXTENDED_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("COUNTValueExtended error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_pdcp_snextended(&ie->pDCP_SNExtended, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_hfnmodified(&ie->hFNModified, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_countvalueextended(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_COUNTVALUEEXTENDED_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("COUNTValueExtended error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_pdcp_snextended(ptr, &ie->pDCP_SNExtended) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_hfnmodified(ptr, &ie->hFNModified) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CriticalityDiagnostics_IE_List DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_criticalitydiagnostics_ie_list(
  LIBLTE_S1AP_CRITICALITYDIAGNOSTICS_IE_LIST_STRUCT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("CriticalityDiagnostics_IE_List pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_criticalitydiagnostics_ie_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_criticalitydiagnostics_ie_list(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CRITICALITYDIAGNOSTICS_IE_LIST_STRUCT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("CriticalityDiagnostics_IE_List unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_criticalitydiagnostics_ie_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Global_ENB_ID SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_global_enb_id(
  LIBLTE_S1AP_GLOBAL_ENB_ID_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Global_ENB_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tbcd_string(&ie->pLMNidentity, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_enb_id(&ie->eNB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_global_enb_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_GLOBAL_ENB_ID_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Global_ENB_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->pLMNidentity) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_enb_id(ptr, &ie->eNB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EPLMNs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:15
LIBLTE_ERROR_ENUM liblte_s1ap_pack_eplmns(
  LIBLTE_S1AP_EPLMNS_STRUCT                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("EPLMNs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 4);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tbcd_string(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_eplmns(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EPLMNS_STRUCT                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 4) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("EPLMNs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABItem SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabitem(
  LIBLTE_S1AP_E_RABITEM_STRUCT                                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_cause(&ie->cause, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABITEM_STRUCT                                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_cause(ptr, &ie->cause) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EUTRAN_CGI SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_eutran_cgi(
  LIBLTE_S1AP_EUTRAN_CGI_STRUCT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("EUTRAN_CGI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tbcd_string(&ie->pLMNidentity, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_cellidentity(&ie->cell_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_eutran_cgi(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EUTRAN_CGI_STRUCT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("EUTRAN_CGI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->pLMNidentity) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_cellidentity(ptr, &ie->cell_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ForbiddenTAs_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_forbiddentas_item(
  LIBLTE_S1AP_FORBIDDENTAS_ITEM_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ForbiddenTAs_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tbcd_string(&ie->pLMN_Identity, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_forbiddentacs(&ie->forbiddenTACs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_forbiddentas_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_FORBIDDENTAS_ITEM_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ForbiddenTAs_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->pLMN_Identity) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_forbiddentacs(ptr, &ie->forbiddenTACs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ForbiddenLAs_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_forbiddenlas_item(
  LIBLTE_S1AP_FORBIDDENLAS_ITEM_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ForbiddenLAs_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tbcd_string(&ie->pLMN_Identity, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_forbiddenlacs(&ie->forbiddenLACs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_forbiddenlas_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_FORBIDDENLAS_ITEM_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ForbiddenLAs_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->pLMN_Identity) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_forbiddenlacs(ptr, &ie->forbiddenLACs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LAI SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lai(
  LIBLTE_S1AP_LAI_STRUCT                                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("LAI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tbcd_string(&ie->pLMNidentity, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_lac(&ie->lAC, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lai(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LAI_STRUCT                                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("LAI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->pLMNidentity) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_lac(ptr, &ie->lAC) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M4Configuration SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m4configuration(
  LIBLTE_S1AP_M4CONFIGURATION_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("M4Configuration error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_m4period(&ie->m4period, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_links_to_log(&ie->m4_links_to_log, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m4configuration(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M4CONFIGURATION_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("M4Configuration error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_m4period(ptr, &ie->m4period) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_links_to_log(ptr, &ie->m4_links_to_log) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MDTPLMNList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:16
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mdtplmnlist(
  LIBLTE_S1AP_MDTPLMNLIST_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("MDTPLMNList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 4);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tbcd_string(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mdtplmnlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MDTPLMNLIST_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 4) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("MDTPLMNList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MMERelaySupportIndicator ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmerelaysupportindicator(
  LIBLTE_S1AP_MMERELAYSUPPORTINDICATOR_ENUM_EXT                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("MMERelaySupportIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mmerelaysupportindicator(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MMERELAYSUPPORTINDICATOR_ENUM_EXT                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("MMERelaySupportIndicator error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_MMERELAYSUPPORTINDICATOR_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PagingPriority ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pagingpriority(
  LIBLTE_S1AP_PAGINGPRIORITY_ENUM_EXT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("PagingPriority error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pagingpriority(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PAGINGPRIORITY_ENUM_EXT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("PagingPriority error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_PAGINGPRIORITY_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PriorityLevel INTEGER
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_prioritylevel(
  LIBLTE_S1AP_PRIORITYLEVEL_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->PriorityLevel
    // lb:0, ub:15
    liblte_value_2_bits(ie->PriorityLevel, ptr, 4);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_prioritylevel(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PRIORITYLEVEL_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Integer - ie->PriorityLevel
    // lb:0, ub:15
    ie->PriorityLevel = (uint8_t)liblte_bits_2_value(ptr, 4);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ECGIListForRestart DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ecgilistforrestart(
  LIBLTE_S1AP_ECGILISTFORRESTART_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ECGIListForRestart pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_eutran_cgi(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ecgilistforrestart(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ECGILISTFORRESTART_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ECGIListForRestart unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SourceeNB_ID SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_sourceenb_id(
  LIBLTE_S1AP_SOURCEENB_ID_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_global_enb_id(&ie->global_ENB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_tai(&ie->selected_TAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_sourceenb_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SOURCEENB_ID_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_global_enb_id(ptr, &ie->global_ENB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_tai(ptr, &ie->selected_TAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ServedPLMNs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:32
LIBLTE_ERROR_ENUM liblte_s1ap_pack_servedplmns(
  LIBLTE_S1AP_SERVEDPLMNS_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ServedPLMNs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 5);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tbcd_string(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_servedplmns(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SERVEDPLMNS_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 5) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ServedPLMNs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SupportedTAs_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_supportedtas_item(
  LIBLTE_S1AP_SUPPORTEDTAS_ITEM_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SupportedTAs_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tac(&ie->tAC, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_bplmns(&ie->broadcastPLMNs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_supportedtas_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SUPPORTEDTAS_ITEM_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SupportedTAs_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tac(ptr, &ie->tAC) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_bplmns(ptr, &ie->broadcastPLMNs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAIListforMDT DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:8
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tailistformdt(
  LIBLTE_S1AP_TAILISTFORMDT_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("TAIListforMDT pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tai(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tailistformdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAILISTFORMDT_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 3) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("TAIListforMDT unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tai(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CompletedCellinTAI_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_completedcellintai_item(
  LIBLTE_S1AP_COMPLETEDCELLINTAI_ITEM_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CompletedCellinTAI_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_eutran_cgi(&ie->eCGI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_completedcellintai_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_COMPLETEDCELLINTAI_ITEM_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CompletedCellinTAI_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->eCGI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TargeteNB_ID SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_targetenb_id(
  LIBLTE_S1AP_TARGETENB_ID_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TargeteNB_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_global_enb_id(&ie->global_ENB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_tai(&ie->selected_TAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_targetenb_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TARGETENB_ID_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TargeteNB_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_global_enb_id(ptr, &ie->global_ENB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_tai(ptr, &ie->selected_TAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TargetBSS_ToSourceBSS_TransparentContainer DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_targetbss_tosourcebss_transparentcontainer(
  LIBLTE_S1AP_TARGETBSS_TOSOURCEBSS_TRANSPARENTCONTAINER_STRUCT       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - TargetBSS-ToSourceBSS-TransparentContainer
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_targetbss_tosourcebss_transparentcontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TARGETBSS_TOSOURCEBSS_TRANSPARENTCONTAINER_STRUCT       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - TargetBSS-ToSourceBSS-TransparentContainer
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAIListForRestart DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:2048
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tailistforrestart(
  LIBLTE_S1AP_TAILISTFORRESTART_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("TAIListForRestart pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 11);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tai(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tailistforrestart(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAILISTFORRESTART_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 11) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("TAIListForRestart unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tai(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UserLocationInformation SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_userlocationinformation(
  LIBLTE_S1AP_USERLOCATIONINFORMATION_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("UserLocationInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_eutran_cgi(&ie->eutran_cgi, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_tai(&ie->tai, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_userlocationinformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_USERLOCATIONINFORMATION_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("UserLocationInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->eutran_cgi) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_tai(ptr, &ie->tai) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ENBX2ExtTLAs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:16
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbx2exttlas(
  LIBLTE_S1AP_ENBX2EXTTLAS_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ENBX2ExtTLAs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 4);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_enbx2exttla(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbx2exttlas(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ENBX2EXTTLAS_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 4) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ENBX2ExtTLAs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_enbx2exttla(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE AllocationAndRetentionPriority SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_allocationandretentionpriority(
  LIBLTE_S1AP_ALLOCATIONANDRETENTIONPRIORITY_STRUCT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("AllocationAndRetentionPriority error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_prioritylevel(&ie->priorityLevel, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum - ie->pre_emptionCapability
    liblte_value_2_bits(ie->pre_emptionCapability, ptr, 1);

    // Enum - ie->pre_emptionVulnerability
    liblte_value_2_bits(ie->pre_emptionVulnerability, ptr, 1);

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_allocationandretentionpriority(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ALLOCATIONANDRETENTIONPRIORITY_STRUCT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("AllocationAndRetentionPriority error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_prioritylevel(ptr, &ie->priorityLevel) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum - ie->pre_emptionCapability
    ie->pre_emptionCapability = (LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_ENUM)liblte_bits_2_value(ptr, 1);

    // Enum - ie->pre_emptionVulnerability
    ie->pre_emptionVulnerability = (LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_ENUM)liblte_bits_2_value(ptr, 1);

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CancelledCellinEAI_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cancelledcellineai_item(
  LIBLTE_S1AP_CANCELLEDCELLINEAI_ITEM_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CancelledCellinEAI_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_eutran_cgi(&ie->eCGI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_numberofbroadcasts(&ie->numberOfBroadcasts, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cancelledcellineai_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CANCELLEDCELLINEAI_ITEM_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CancelledCellinEAI_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->eCGI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_numberofbroadcasts(ptr, &ie->numberOfBroadcasts) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CancelledCellinTAI_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cancelledcellintai_item(
  LIBLTE_S1AP_CANCELLEDCELLINTAI_ITEM_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CancelledCellinTAI_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_eutran_cgi(&ie->eCGI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_numberofbroadcasts(&ie->numberOfBroadcasts, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cancelledcellintai_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CANCELLEDCELLINTAI_ITEM_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CancelledCellinTAI_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->eCGI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_numberofbroadcasts(ptr, &ie->numberOfBroadcasts) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CellID_Broadcast_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellid_broadcast_item(
  LIBLTE_S1AP_CELLID_BROADCAST_ITEM_STRUCT                           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellID_Broadcast_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_eutran_cgi(&ie->eCGI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellid_broadcast_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELLID_BROADCAST_ITEM_STRUCT                           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellID_Broadcast_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->eCGI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CellID_Cancelled_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellid_cancelled_item(
  LIBLTE_S1AP_CELLID_CANCELLED_ITEM_STRUCT                           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellID_Cancelled_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_eutran_cgi(&ie->eCGI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_numberofbroadcasts(&ie->numberOfBroadcasts, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellid_cancelled_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELLID_CANCELLED_ITEM_STRUCT                           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellID_Cancelled_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->eCGI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_numberofbroadcasts(ptr, &ie->numberOfBroadcasts) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CellIdListforMDT DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:32
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellidlistformdt(
  LIBLTE_S1AP_CELLIDLISTFORMDT_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("CellIdListforMDT pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 5);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_eutran_cgi(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellidlistformdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELLIDLISTFORMDT_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 5) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("CellIdListforMDT unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CSG_Id STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_csg_id(
  LIBLTE_S1AP_CSG_ID_STRUCT                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - CSG-Id
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_CSG_ID_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_csg_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CSG_ID_STRUCT                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - CSG-Id
    liblte_align_up(ptr, 8);
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_CSG_ID_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CSG_IdList_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_csg_idlist_item(
  LIBLTE_S1AP_CSG_IDLIST_ITEM_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CSG_IdList_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_csg_id(&ie->cSG_Id, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_csg_idlist_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CSG_IDLIST_ITEM_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CSG_IdList_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_csg_id(ptr, &ie->cSG_Id) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Direct_Forwarding_Path_Availability ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_direct_forwarding_path_availability(
  LIBLTE_S1AP_DIRECT_FORWARDING_PATH_AVAILABILITY_ENUM_EXT           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Direct_Forwarding_Path_Availability error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_direct_forwarding_path_availability(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_DIRECT_FORWARDING_PATH_AVAILABILITY_ENUM_EXT           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Direct_Forwarding_Path_Availability error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_DIRECT_FORWARDING_PATH_AVAILABILITY_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CompletedCellinEAI_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_completedcellineai_item(
  LIBLTE_S1AP_COMPLETEDCELLINEAI_ITEM_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CompletedCellinEAI_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_eutran_cgi(&ie->eCGI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_completedcellineai_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_COMPLETEDCELLINEAI_ITEM_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CompletedCellinEAI_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->eCGI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABInformationList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabinformationlist(
  LIBLTE_S1AP_E_RABINFORMATIONLIST_STRUCT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABInformationList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabinformationlistitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABINFORMATIONLISTITEM,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabinformationlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABINFORMATIONLIST_STRUCT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABInformationList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABINFORMATIONLISTITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabinformationlistitem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ForbiddenTAs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:16
LIBLTE_ERROR_ENUM liblte_s1ap_pack_forbiddentas(
  LIBLTE_S1AP_FORBIDDENTAS_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ForbiddenTAs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 4);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_forbiddentas_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_forbiddentas(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_FORBIDDENTAS_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 4) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ForbiddenTAs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_forbiddentas_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE GUMMEI SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_gummei(
  LIBLTE_S1AP_GUMMEI_STRUCT                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("GUMMEI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tbcd_string(&ie->pLMN_Identity, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_mme_group_id(&ie->mME_Group_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_mme_code(&ie->mME_Code, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_gummei(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_GUMMEI_STRUCT                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("GUMMEI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->pLMN_Identity) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_mme_group_id(ptr, &ie->mME_Group_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_mme_code(ptr, &ie->mME_Code) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LoggedMDT SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_loggedmdt(
  LIBLTE_S1AP_LOGGEDMDT_STRUCT                                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("LoggedMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    // Enum - ie->loggingInterval
    liblte_value_2_bits(ie->loggingInterval, ptr, 3);

    // Enum - ie->loggingDuration
    liblte_value_2_bits(ie->loggingDuration, ptr, 3);

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_loggedmdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LOGGEDMDT_STRUCT                                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("LoggedMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    // Enum - ie->loggingInterval
    ie->loggingInterval = (LIBLTE_S1AP_LOGGINGINTERVAL_ENUM)liblte_bits_2_value(ptr, 3);

    // Enum - ie->loggingDuration
    ie->loggingDuration = (LIBLTE_S1AP_LOGGINGDURATION_ENUM)liblte_bits_2_value(ptr, 3);

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE NASSecurityParametersfromE_UTRAN DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_nassecurityparametersfrome_utran(
  LIBLTE_S1AP_NASSECURITYPARAMETERSFROME_UTRAN_STRUCT                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - NASSecurityParametersfromE-UTRAN
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_nassecurityparametersfrome_utran(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_NASSECURITYPARAMETERSFROME_UTRAN_STRUCT                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - NASSecurityParametersfromE-UTRAN
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ReportAmountMDT ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_reportamountmdt(
  LIBLTE_S1AP_REPORTAMOUNTMDT_ENUM                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    liblte_value_2_bits(*ie, ptr, 3);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_reportamountmdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_REPORTAMOUNTMDT_ENUM                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Enum - *ie
    *ie = (LIBLTE_S1AP_REPORTAMOUNTMDT_ENUM)liblte_bits_2_value(ptr, 3);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ServedGUMMEIsItem SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_servedgummeisitem(
  LIBLTE_S1AP_SERVEDGUMMEISITEM_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ServedGUMMEIsItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_servedplmns(&ie->servedPLMNs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_servedgroupids(&ie->servedGroupIDs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_servedmmecs(&ie->servedMMECs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_servedgummeisitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SERVEDGUMMEISITEM_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ServedGUMMEIsItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_servedplmns(ptr, &ie->servedPLMNs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_servedgroupids(ptr, &ie->servedGroupIDs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_servedmmecs(ptr, &ie->servedMMECs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE S_TMSI SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_s_tmsi(
  LIBLTE_S1AP_S_TMSI_STRUCT                                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("S_TMSI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_mme_code(&ie->mMEC, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_m_tmsi(&ie->m_TMSI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_s_tmsi(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_S_TMSI_STRUCT                                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("S_TMSI error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_mme_code(ptr, &ie->mMEC) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_m_tmsi(ptr, &ie->m_TMSI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAIListforWarning DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tailistforwarning(
  LIBLTE_S1AP_TAILISTFORWARNING_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("TAIListforWarning pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tai(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tailistforwarning(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAILISTFORWARNING_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("TAIListforWarning unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tai(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CompletedCellinTAI DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_completedcellintai(
  LIBLTE_S1AP_COMPLETEDCELLINTAI_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("CompletedCellinTAI pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_completedcellintai_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_completedcellintai(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_COMPLETEDCELLINTAI_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("CompletedCellinTAI unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_completedcellintai_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TargetRNC_ID SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_targetrnc_id(
  LIBLTE_S1AP_TARGETRNC_ID_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TargetRNC_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->rAC_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->extendedRNC_ID_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_lai(&ie->lAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->rAC_present) {
      if(liblte_s1ap_pack_rac(&ie->rAC, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(liblte_s1ap_pack_rnc_id(&ie->rNC_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->extendedRNC_ID_present) {
      if(liblte_s1ap_pack_extendedrnc_id(&ie->extendedRNC_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_targetrnc_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TARGETRNC_ID_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TargetRNC_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->rAC_present = liblte_bits_2_value(ptr, 1);
    ie->extendedRNC_ID_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_lai(ptr, &ie->lAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->rAC_present) {
      if(liblte_s1ap_unpack_rac(ptr, &ie->rAC) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(liblte_s1ap_unpack_rnc_id(ptr, &ie->rNC_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->extendedRNC_ID_present) {
      if(liblte_s1ap_unpack_extendedrnc_id(ptr, &ie->extendedRNC_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UE_associatedLogicalS1_ConnectionItem SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(
  LIBLTE_S1AP_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM_STRUCT           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("UE_associatedLogicalS1_ConnectionItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->mME_UE_S1AP_ID_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->eNB_UE_S1AP_ID_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(ie->mME_UE_S1AP_ID_present) {
      if(liblte_s1ap_pack_mme_ue_s1ap_id(&ie->mME_UE_S1AP_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->eNB_UE_S1AP_ID_present) {
      if(liblte_s1ap_pack_enb_ue_s1ap_id(&ie->eNB_UE_S1AP_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_associatedlogicals1_connectionitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM_STRUCT           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("UE_associatedLogicalS1_ConnectionItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->mME_UE_S1AP_ID_present = liblte_bits_2_value(ptr, 1);
    ie->eNB_UE_S1AP_ID_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(ie->mME_UE_S1AP_ID_present) {
      if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &ie->mME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->eNB_UE_S1AP_ID_present) {
      if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &ie->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UEPagingID CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uepagingid(
  LIBLTE_S1AP_UEPAGINGID_STRUCT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("UEPagingID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_UEPAGINGID_CHOICE_S_TMSI) {
      if(liblte_s1ap_pack_s_tmsi(&ie->choice.s_TMSI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_UEPAGINGID_CHOICE_IMSI) {
      if(liblte_s1ap_pack_imsi(&ie->choice.iMSI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uepagingid(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UEPAGINGID_STRUCT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("UEPagingID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_UEPAGINGID_CHOICE_ENUM)liblte_bits_2_value(ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_UEPAGINGID_CHOICE_S_TMSI) {
      if(liblte_s1ap_unpack_s_tmsi(ptr, &ie->choice.s_TMSI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_UEPAGINGID_CHOICE_IMSI) {
      if(liblte_s1ap_unpack_imsi(ptr, &ie->choice.iMSI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Bearers_SubjectToStatusTransfer_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_item(
  LIBLTE_S1AP_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEM_STRUCT            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Bearers_SubjectToStatusTransfer_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->receiveStatusofULPDCPSDUs_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_countvalue(&ie->uL_COUNTvalue, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_countvalue(&ie->dL_COUNTvalue, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->receiveStatusofULPDCPSDUs_present) {
      if(liblte_s1ap_pack_receivestatusofulpdcpsdus(&ie->receiveStatusofULPDCPSDUs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_bearers_subjecttostatustransfer_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEM_STRUCT            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Bearers_SubjectToStatusTransfer_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->receiveStatusofULPDCPSDUs_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_countvalue(ptr, &ie->uL_COUNTvalue) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_countvalue(ptr, &ie->dL_COUNTvalue) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->receiveStatusofULPDCPSDUs_present) {
      if(liblte_s1ap_unpack_receivestatusofulpdcpsdus(ptr, &ie->receiveStatusofULPDCPSDUs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CancelledCellinEAI DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cancelledcellineai(
  LIBLTE_S1AP_CANCELLEDCELLINEAI_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("CancelledCellinEAI pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_cancelledcellineai_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cancelledcellineai(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CANCELLEDCELLINEAI_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("CancelledCellinEAI unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_cancelledcellineai_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CellID_Broadcast DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellid_broadcast(
  LIBLTE_S1AP_CELLID_BROADCAST_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("CellID_Broadcast pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_cellid_broadcast_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellid_broadcast(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELLID_BROADCAST_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("CellID_Broadcast unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_cellid_broadcast_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CellBasedMDT SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellbasedmdt(
  LIBLTE_S1AP_CELLBASEDMDT_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellBasedMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_cellidlistformdt(&ie->cellIdListforMDT, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellbasedmdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELLBASEDMDT_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellBasedMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_cellidlistformdt(ptr, &ie->cellIdListforMDT) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CSG_IdList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_csg_idlist(
  LIBLTE_S1AP_CSG_IDLIST_STRUCT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("CSG_IdList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_csg_idlist_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_csg_idlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CSG_IDLIST_STRUCT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("CSG_IdList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_csg_idlist_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ECGIList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ecgilist(
  LIBLTE_S1AP_ECGILIST_STRUCT                                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ECGIList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_eutran_cgi(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ecgilist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ECGILIST_STRUCT                                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ECGIList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EmergencyAreaID_Cancelled_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_emergencyareaid_cancelled_item(
  LIBLTE_S1AP_EMERGENCYAREAID_CANCELLED_ITEM_STRUCT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("EmergencyAreaID_Cancelled_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_emergencyareaid(&ie->emergencyAreaID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_cancelledcellineai(&ie->cancelledCellinEAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_emergencyareaid_cancelled_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EMERGENCYAREAID_CANCELLED_ITEM_STRUCT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("EmergencyAreaID_Cancelled_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_emergencyareaid(ptr, &ie->emergencyAreaID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_cancelledcellineai(ptr, &ie->cancelledCellinEAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE GERAN_Cell_ID SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_geran_cell_id(
  LIBLTE_S1AP_GERAN_CELL_ID_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("GERAN_Cell_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_lai(&ie->lAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_rac(&ie->rAC, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_ci(&ie->cI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_geran_cell_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_GERAN_CELL_ID_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("GERAN_Cell_ID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_lai(ptr, &ie->lAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_rac(ptr, &ie->rAC) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_ci(ptr, &ie->cI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rablist(
  LIBLTE_S1AP_E_RABLIST_STRUCT                                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABITEM,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rablist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABLIST_STRUCT                                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabitem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ForbiddenLAs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:16
LIBLTE_ERROR_ENUM liblte_s1ap_pack_forbiddenlas(
  LIBLTE_S1AP_FORBIDDENLAS_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ForbiddenLAs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 4);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_forbiddenlas_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_forbiddenlas(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_FORBIDDENLAS_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 4) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ForbiddenLAs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_forbiddenlas_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MDT_Location_Info STATIC BIT STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mdt_location_info(
  LIBLTE_S1AP_MDT_LOCATION_INFO_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - MDT-Location-Info
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MDT_LOCATION_INFO_BIT_STRING_LEN;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mdt_location_info(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MDT_LOCATION_INFO_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Static bit string - MDT-Location-Info
    uint32_t i;
    for(i=0;i<LIBLTE_S1AP_MDT_LOCATION_INFO_BIT_STRING_LEN;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 1);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE M1PeriodicReporting SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m1periodicreporting(
  LIBLTE_S1AP_M1PERIODICREPORTING_STRUCT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("M1PeriodicReporting error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    // Enum - ie->reportInterval
    liblte_value_2_bits(ie->reportInterval, ptr, 4);

    // Enum - ie->reportAmount
    liblte_value_2_bits(ie->reportAmount, ptr, 3);

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m1periodicreporting(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_M1PERIODICREPORTING_STRUCT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("M1PeriodicReporting error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    // Enum - ie->reportInterval
    ie->reportInterval = (LIBLTE_S1AP_REPORTINTERVALMDT_ENUM)liblte_bits_2_value(ptr, 4);

    // Enum - ie->reportAmount
    ie->reportAmount = (LIBLTE_S1AP_REPORTAMOUNTMDT_ENUM)liblte_bits_2_value(ptr, 3);

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}


/*******************************************************************************
/* ProtocolIE eHRPD_Sector_ID DYNAMIC OCTET STRING
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ehrpd_sector_id(
  LIBLTE_S1AP_EHRPD_SECTOR_ID_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - eHRPD-Sector-ID
    // Length
    if(ie->n_octets < 128) {
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 7);
    } else if(ie->n_octets < 16383) {
      liblte_value_2_bits(1,            ptr, 1);
      liblte_value_2_bits(0,            ptr, 1);
      liblte_value_2_bits(ie->n_octets, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
    
    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      liblte_value_2_bits(ie->buffer[i], ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ehrpd_sector_id(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EHRPD_SECTOR_ID_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Dynamic octet string - eHRPD-Sector-ID
    // Length
    if(0 == liblte_bits_2_value(ptr, 1)) {
      ie->n_octets = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        ie->n_octets = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Octets
    uint32_t i;
    for(i=0;i<ie->n_octets;i++) {
      ie->buffer[i] = liblte_bits_2_value(ptr, 8);
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}


/*******************************************************************************
/* ProtocolIE RIMRoutingAddress CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_rimroutingaddress(
  LIBLTE_S1AP_RIMROUTINGADDRESS_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("RIMRoutingAddress error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_RIMROUTINGADDRESS_CHOICE_GERAN_CELL_ID) {
      if(liblte_s1ap_pack_geran_cell_id(&ie->choice.gERAN_Cell_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_RIMROUTINGADDRESS_CHOICE_TARGETRNC_ID) {
      if(liblte_s1ap_pack_targetrnc_id(&ie->choice.targetRNC_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_RIMROUTINGADDRESS_CHOICE_EHRPD_SECTOR_ID) {
      if(liblte_s1ap_pack_ehrpd_sector_id(&ie->choice.eHRPD_Sector_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_rimroutingaddress(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RIMROUTINGADDRESS_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("RIMRoutingAddress error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_RIMROUTINGADDRESS_CHOICE_ENUM)liblte_bits_2_value(ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_RIMROUTINGADDRESS_CHOICE_GERAN_CELL_ID) {
      if(liblte_s1ap_unpack_geran_cell_id(ptr, &ie->choice.gERAN_Cell_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_RIMROUTINGADDRESS_CHOICE_TARGETRNC_ID) {
      if(liblte_s1ap_unpack_targetrnc_id(ptr, &ie->choice.targetRNC_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_RIMROUTINGADDRESS_CHOICE_EHRPD_SECTOR_ID) {
      if(liblte_s1ap_unpack_ehrpd_sector_id(ptr, &ie->choice.eHRPD_Sector_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ServedGUMMEIs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:8
LIBLTE_ERROR_ENUM liblte_s1ap_pack_servedgummeis(
  LIBLTE_S1AP_SERVEDGUMMEIS_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("ServedGUMMEIs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 3);
    // liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_servedgummeisitem(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_servedgummeis(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SERVEDGUMMEIS_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 3) + 1;
    // liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("ServedGUMMEIs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_servedgummeisitem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAIBasedMDT SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_taibasedmdt(
  LIBLTE_S1AP_TAIBASEDMDT_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAIBasedMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tailistformdt(&ie->tAIListforMDT, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_taibasedmdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAIBASEDMDT_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAIBasedMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tailistformdt(ptr, &ie->tAIListforMDT) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAI_Broadcast_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tai_broadcast_item(
  LIBLTE_S1AP_TAI_BROADCAST_ITEM_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAI_Broadcast_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tai(&ie->tAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_completedcellintai(&ie->completedCellinTAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tai_broadcast_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAI_BROADCAST_ITEM_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAI_Broadcast_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tai(ptr, &ie->tAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_completedcellintai(ptr, &ie->completedCellinTAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TargetID CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_targetid(
  LIBLTE_S1AP_TARGETID_STRUCT                                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TargetID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_TARGETID_CHOICE_TARGETENB_ID) {
      if(liblte_s1ap_pack_targetenb_id(&ie->choice.targeteNB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_TARGETID_CHOICE_TARGETRNC_ID) {
      if(liblte_s1ap_pack_targetrnc_id(&ie->choice.targetRNC_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_TARGETID_CHOICE_CGI) {
      if(liblte_s1ap_pack_cgi(&ie->choice.cGI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_targetid(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TARGETID_STRUCT                                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TargetID error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_TARGETID_CHOICE_ENUM)liblte_bits_2_value(ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_TARGETID_CHOICE_TARGETENB_ID) {
      if(liblte_s1ap_unpack_targetenb_id(ptr, &ie->choice.targeteNB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_TARGETID_CHOICE_TARGETRNC_ID) {
      if(liblte_s1ap_unpack_targetrnc_id(ptr, &ie->choice.targetRNC_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_TARGETID_CHOICE_CGI) {
      if(liblte_s1ap_unpack_cgi(ptr, &ie->choice.cGI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE WarningAreaList CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_warningarealist(
  LIBLTE_S1AP_WARNINGAREALIST_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("WarningAreaList error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_WARNINGAREALIST_CHOICE_CELLIDLIST) {
      if(liblte_s1ap_pack_ecgilist(&ie->choice.cellIDList, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_WARNINGAREALIST_CHOICE_TRACKINGAREALISTFORWARNING) {
      if(liblte_s1ap_pack_tailistforwarning(&ie->choice.trackingAreaListforWarning, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_WARNINGAREALIST_CHOICE_EMERGENCYAREAIDLIST) {
      if(liblte_s1ap_pack_emergencyareaidlist(&ie->choice.emergencyAreaIDList, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_warningarealist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_WARNINGAREALIST_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("WarningAreaList error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_WARNINGAREALIST_CHOICE_ENUM)liblte_bits_2_value(ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_WARNINGAREALIST_CHOICE_CELLIDLIST) {
      if(liblte_s1ap_unpack_ecgilist(ptr, &ie->choice.cellIDList) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_WARNINGAREALIST_CHOICE_TRACKINGAREALISTFORWARNING) {
      if(liblte_s1ap_unpack_tailistforwarning(ptr, &ie->choice.trackingAreaListforWarning) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_WARNINGAREALIST_CHOICE_EMERGENCYAREAIDLIST) {
      if(liblte_s1ap_unpack_emergencyareaidlist(ptr, &ie->choice.emergencyAreaIDList) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE AreaScopeOfMDT CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_areascopeofmdt(
  LIBLTE_S1AP_AREASCOPEOFMDT_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("AreaScopeOfMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_AREASCOPEOFMDT_CHOICE_CELLBASED) {
      if(liblte_s1ap_pack_cellbasedmdt(&ie->choice.cellBased, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_AREASCOPEOFMDT_CHOICE_TABASED) {
      if(liblte_s1ap_pack_tabasedmdt(&ie->choice.tABased, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_AREASCOPEOFMDT_CHOICE_PLMNWIDE) {
      } else if(ie->choice_type == LIBLTE_S1AP_AREASCOPEOFMDT_CHOICE_TAIBASED) {
      if(liblte_s1ap_pack_taibasedmdt(&ie->choice.tAIBased, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_areascopeofmdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_AREASCOPEOFMDT_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("AreaScopeOfMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_AREASCOPEOFMDT_CHOICE_ENUM)liblte_bits_2_value(ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_AREASCOPEOFMDT_CHOICE_CELLBASED) {
      if(liblte_s1ap_unpack_cellbasedmdt(ptr, &ie->choice.cellBased) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_AREASCOPEOFMDT_CHOICE_TABASED) {
      if(liblte_s1ap_unpack_tabasedmdt(ptr, &ie->choice.tABased) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_AREASCOPEOFMDT_CHOICE_PLMNWIDE) {
      } else if(ie->choice_type == LIBLTE_S1AP_AREASCOPEOFMDT_CHOICE_TAIBASED) {
      if(liblte_s1ap_unpack_taibasedmdt(ptr, &ie->choice.tAIBased) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CancelledCellinTAI DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cancelledcellintai(
  LIBLTE_S1AP_CANCELLEDCELLINTAI_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("CancelledCellinTAI pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_cancelledcellintai_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cancelledcellintai(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CANCELLEDCELLINTAI_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("CancelledCellinTAI unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_cancelledcellintai_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CellType SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltype(
  LIBLTE_S1AP_CELLTYPE_STRUCT                                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_cell_size(&ie->cell_Size, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_celltype(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELLTYPE_STRUCT                                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CellType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_cell_size(ptr, &ie->cell_Size) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EmergencyAreaID_Cancelled DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_emergencyareaid_cancelled(
  LIBLTE_S1AP_EMERGENCYAREAID_CANCELLED_STRUCT                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("EmergencyAreaID_Cancelled pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_emergencyareaid_cancelled_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_emergencyareaid_cancelled(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EMERGENCYAREAID_CANCELLED_STRUCT                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("EmergencyAreaID_Cancelled unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_emergencyareaid_cancelled_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE GUMMEIList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_gummeilist(
  LIBLTE_S1AP_GUMMEILIST_STRUCT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("GUMMEIList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_gummei(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_gummeilist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_GUMMEILIST_STRUCT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("GUMMEIList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_gummei(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABLevelQoSParameters SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rablevelqosparameters(
  LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABLevelQoSParameters error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->gbrQosInformation_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_qci(&ie->qCI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_allocationandretentionpriority(&ie->allocationRetentionPriority, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->gbrQosInformation_present) {
      if(liblte_s1ap_pack_gbr_qosinformation(&ie->gbrQosInformation, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rablevelqosparameters(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABLevelQoSParameters error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->gbrQosInformation_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_qci(ptr, &ie->qCI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_allocationandretentionpriority(ptr, &ie->allocationRetentionPriority) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->gbrQosInformation_present) {
      if(liblte_s1ap_unpack_gbr_qosinformation(ptr, &ie->gbrQosInformation) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LastVisitedEUTRANCellInformation SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lastvisitedeutrancellinformation(
  LIBLTE_S1AP_LASTVISITEDEUTRANCELLINFORMATION_STRUCT                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("LastVisitedEUTRANCellInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_eutran_cgi(&ie->global_Cell_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_celltype(&ie->cellType, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_time_ue_stayedincell(&ie->time_UE_StayedInCell, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lastvisitedeutrancellinformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LASTVISITEDEUTRANCELLINFORMATION_STRUCT                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("LastVisitedEUTRANCellInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->global_Cell_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_celltype(ptr, &ie->cellType) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_time_ue_stayedincell(ptr, &ie->time_UE_StayedInCell) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE RIMTransfer SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_rimtransfer(
  LIBLTE_S1AP_RIMTRANSFER_STRUCT                                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("RIMTransfer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->rIMRoutingAddress_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_riminformation(&ie->rIMInformation, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->rIMRoutingAddress_present) {
      if(liblte_s1ap_pack_rimroutingaddress(&ie->rIMRoutingAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_rimtransfer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RIMTRANSFER_STRUCT                                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("RIMTransfer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->rIMRoutingAddress_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_riminformation(ptr, &ie->rIMInformation) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->rIMRoutingAddress_present) {
      if(liblte_s1ap_unpack_rimroutingaddress(ptr, &ie->rIMRoutingAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SupportedTAs DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_supportedtas(
  LIBLTE_S1AP_SUPPORTEDTAS_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("SupportedTAs pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_supportedtas_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_supportedtas(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SUPPORTEDTAS_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("SupportedTAs unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_supportedtas_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAI_Cancelled_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tai_cancelled_item(
  LIBLTE_S1AP_TAI_CANCELLED_ITEM_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAI_Cancelled_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tai(&ie->tAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_cancelledcellintai(&ie->cancelledCellinTAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tai_cancelled_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAI_CANCELLED_ITEM_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAI_Cancelled_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tai(ptr, &ie->tAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_cancelledcellintai(ptr, &ie->cancelledCellinTAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE X2TNLConfigurationInfo SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_x2tnlconfigurationinfo(
  LIBLTE_S1AP_X2TNLCONFIGURATIONINFO_STRUCT                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("X2TNLConfigurationInfo error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_enbx2tlas(&ie->eNBX2TransportLayerAddresses, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_x2tnlconfigurationinfo(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_X2TNLCONFIGURATIONINFO_STRUCT                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("X2TNLConfigurationInfo error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_enbx2tlas(ptr, &ie->eNBX2TransportLayerAddresses) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List Bearers_SubjectToStatusTransferList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransferlist(
  LIBLTE_S1AP_BEARERS_SUBJECTTOSTATUSTRANSFERLIST_STRUCT             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("Bearers_SubjectToStatusTransferList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_bearers_subjecttostatustransfer_item(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEM,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_bearers_subjecttostatustransferlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_BEARERS_SUBJECTTOSTATUSTRANSFERLIST_STRUCT             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("Bearers_SubjectToStatusTransferList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_bearers_subjecttostatustransfer_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CellID_Cancelled DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellid_cancelled(
  LIBLTE_S1AP_CELLID_CANCELLED_STRUCT                                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("CellID_Cancelled pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_cellid_cancelled_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellid_cancelled(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CELLID_CANCELLED_STRUCT                                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("CellID_Cancelled unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_cellid_cancelled_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CompletedCellinEAI DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_completedcellineai(
  LIBLTE_S1AP_COMPLETEDCELLINEAI_STRUCT                              *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("CompletedCellinEAI pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_completedcellineai_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_completedcellineai(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_COMPLETEDCELLINEAI_STRUCT                              *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("CompletedCellinEAI unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_completedcellineai_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE HandoverRestrictionList SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrestrictionlist(
  LIBLTE_S1AP_HANDOVERRESTRICTIONLIST_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("HandoverRestrictionList error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->equivalentPLMNs_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->forbiddenTAs_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->forbiddenLAs_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->forbiddenInterRATs_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tbcd_string(&ie->servingPLMN, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->equivalentPLMNs_present) {
      if(liblte_s1ap_pack_eplmns(&ie->equivalentPLMNs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->forbiddenTAs_present) {
      if(liblte_s1ap_pack_forbiddentas(&ie->forbiddenTAs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->forbiddenLAs_present) {
      if(liblte_s1ap_pack_forbiddenlas(&ie->forbiddenLAs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->forbiddenInterRATs_present) {
      if(liblte_s1ap_pack_forbiddeninterrats(&ie->forbiddenInterRATs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handoverrestrictionlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_HANDOVERRESTRICTIONLIST_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("HandoverRestrictionList error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->equivalentPLMNs_present = liblte_bits_2_value(ptr, 1);
    ie->forbiddenTAs_present = liblte_bits_2_value(ptr, 1);
    ie->forbiddenLAs_present = liblte_bits_2_value(ptr, 1);
    ie->forbiddenInterRATs_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tbcd_string(ptr, &ie->servingPLMN) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->equivalentPLMNs_present) {
      if(liblte_s1ap_unpack_eplmns(ptr, &ie->equivalentPLMNs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->forbiddenTAs_present) {
      if(liblte_s1ap_unpack_forbiddentas(ptr, &ie->forbiddenTAs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->forbiddenLAs_present) {
      if(liblte_s1ap_unpack_forbiddenlas(ptr, &ie->forbiddenLAs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->forbiddenInterRATs_present) {
      if(liblte_s1ap_unpack_forbiddeninterrats(ptr, &ie->forbiddenInterRATs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE LastVisitedCell_Item CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lastvisitedcell_item(
  LIBLTE_S1AP_LASTVISITEDCELL_ITEM_STRUCT                            *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("LastVisitedCell_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_LASTVISITEDCELL_ITEM_CHOICE_E_UTRAN_CELL) {
      if(liblte_s1ap_pack_lastvisitedeutrancellinformation(&ie->choice.e_UTRAN_Cell, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_LASTVISITEDCELL_ITEM_CHOICE_UTRAN_CELL) {
      if(liblte_s1ap_pack_lastvisitedutrancellinformation(&ie->choice.uTRAN_Cell, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_LASTVISITEDCELL_ITEM_CHOICE_GERAN_CELL) {
      if(liblte_s1ap_pack_lastvisitedgerancellinformation(&ie->choice.gERAN_Cell, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lastvisitedcell_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_LASTVISITEDCELL_ITEM_STRUCT                            *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("LastVisitedCell_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_LASTVISITEDCELL_ITEM_CHOICE_ENUM)liblte_bits_2_value(ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_LASTVISITEDCELL_ITEM_CHOICE_E_UTRAN_CELL) {
      if(liblte_s1ap_unpack_lastvisitedeutrancellinformation(ptr, &ie->choice.e_UTRAN_Cell) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_LASTVISITEDCELL_ITEM_CHOICE_UTRAN_CELL) {
      if(liblte_s1ap_unpack_lastvisitedutrancellinformation(ptr, &ie->choice.uTRAN_Cell) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_LASTVISITEDCELL_ITEM_CHOICE_GERAN_CELL) {
      if(liblte_s1ap_unpack_lastvisitedgerancellinformation(ptr, &ie->choice.gERAN_Cell) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SONInformationReply SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_soninformationreply(
  LIBLTE_S1AP_SONINFORMATIONREPLY_STRUCT                             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SONInformationReply error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->x2TNLConfigurationInfo_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(ie->x2TNLConfigurationInfo_present) {
      if(liblte_s1ap_pack_x2tnlconfigurationinfo(&ie->x2TNLConfigurationInfo, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_soninformationreply(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SONINFORMATIONREPLY_STRUCT                             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SONInformationReply error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->x2TNLConfigurationInfo_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(ie->x2TNLConfigurationInfo_present) {
      if(liblte_s1ap_unpack_x2tnlconfigurationinfo(ptr, &ie->x2TNLConfigurationInfo) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAI_Broadcast DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tai_broadcast(
  LIBLTE_S1AP_TAI_BROADCAST_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("TAI_Broadcast pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tai_broadcast_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tai_broadcast(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAI_BROADCAST_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("TAI_Broadcast unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tai_broadcast_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TimeToWait ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_timetowait(
  LIBLTE_S1AP_TIMETOWAIT_ENUM_EXT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TimeToWait error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 3);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_timetowait(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TIMETOWAIT_ENUM_EXT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TimeToWait error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_TIMETOWAIT_ENUM)liblte_bits_2_value(ptr, 3);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE UE_HistoryInformation DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:16
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_historyinformation(
  LIBLTE_S1AP_UE_HISTORYINFORMATION_STRUCT                           *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("UE_HistoryInformation pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 4);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_lastvisitedcell_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_historyinformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UE_HISTORYINFORMATION_STRUCT                           *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 4) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("UE_HistoryInformation unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_lastvisitedcell_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE CriticalityDiagnostics SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_criticalitydiagnostics(
  LIBLTE_S1AP_CRITICALITYDIAGNOSTICS_STRUCT                          *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("CriticalityDiagnostics error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->procedureCode_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->triggeringMessage_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->procedureCriticality_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iEsCriticalityDiagnostics_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(ie->procedureCode_present) {
      if(liblte_s1ap_pack_procedurecode(&ie->procedureCode, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->triggeringMessage_present) {
      // Enum - ie->triggeringMessage
    liblte_value_2_bits(ie->triggeringMessage, ptr, 2);
    }

    if(ie->procedureCriticality_present) {
      // Enum - ie->procedureCriticality
    liblte_value_2_bits(ie->procedureCriticality, ptr, 2);
    }

    if(ie->iEsCriticalityDiagnostics_present) {
      if(liblte_s1ap_pack_criticalitydiagnostics_ie_list(&ie->iEsCriticalityDiagnostics, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_criticalitydiagnostics(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_CRITICALITYDIAGNOSTICS_STRUCT                          *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("CriticalityDiagnostics error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->procedureCode_present = liblte_bits_2_value(ptr, 1);
    ie->triggeringMessage_present = liblte_bits_2_value(ptr, 1);
    ie->procedureCriticality_present = liblte_bits_2_value(ptr, 1);
    ie->iEsCriticalityDiagnostics_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(ie->procedureCode_present) {
      if(liblte_s1ap_unpack_procedurecode(ptr, &ie->procedureCode) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->triggeringMessage_present) {
      // Enum - ie->triggeringMessage
    ie->triggeringMessage = (LIBLTE_S1AP_TRIGGERINGMESSAGE_ENUM)liblte_bits_2_value(ptr, 2);
    }

    if(ie->procedureCriticality_present) {
      // Enum - ie->procedureCriticality
    ie->procedureCriticality = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);
    }

    if(ie->iEsCriticalityDiagnostics_present) {
      if(liblte_s1ap_unpack_criticalitydiagnostics_ie_list(ptr, &ie->iEsCriticalityDiagnostics) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EmergencyAreaID_Broadcast_Item SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_emergencyareaid_broadcast_item(
  LIBLTE_S1AP_EMERGENCYAREAID_BROADCAST_ITEM_STRUCT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("EmergencyAreaID_Broadcast_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_emergencyareaid(&ie->emergencyAreaID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_completedcellineai(&ie->completedCellinEAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_emergencyareaid_broadcast_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EMERGENCYAREAID_BROADCAST_ITEM_STRUCT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("EmergencyAreaID_Broadcast_Item error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_emergencyareaid(ptr, &ie->emergencyAreaID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_completedcellineai(ptr, &ie->completedCellinEAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ImmediateMDT SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt(
  LIBLTE_S1AP_IMMEDIATEMDT_STRUCT                                    *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ImmediateMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->m1thresholdeventA2_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->m1periodicReporting_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_measurementstoactivate(&ie->measurementsToActivate, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_m1reportingtrigger(&ie->m1reportingTrigger, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->m1thresholdeventA2_present) {
      if(liblte_s1ap_pack_m1thresholdeventa2(&ie->m1thresholdeventA2, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->m1periodicReporting_present) {
      if(liblte_s1ap_pack_m1periodicreporting(&ie->m1periodicReporting, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_immediatemdt(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_IMMEDIATEMDT_STRUCT                                    *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ImmediateMDT error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->m1thresholdeventA2_present = liblte_bits_2_value(ptr, 1);
    ie->m1periodicReporting_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_measurementstoactivate(ptr, &ie->measurementsToActivate) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_m1reportingtrigger(ptr, &ie->m1reportingTrigger) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->m1thresholdeventA2_present) {
      if(liblte_s1ap_unpack_m1thresholdeventa2(ptr, &ie->m1thresholdeventA2) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->m1periodicReporting_present) {
      if(liblte_s1ap_unpack_m1periodicreporting(ptr, &ie->m1periodicReporting) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MDTMode CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mdtmode(
  LIBLTE_S1AP_MDTMODE_STRUCT                                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("MDTMode error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_MDTMODE_CHOICE_IMMEDIATEMDT) {
      if(liblte_s1ap_pack_immediatemdt(&ie->choice.immediateMDT, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_MDTMODE_CHOICE_LOGGEDMDT) {
      if(liblte_s1ap_pack_loggedmdt(&ie->choice.loggedMDT, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mdtmode(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MDTMODE_STRUCT                                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("MDTMode error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_MDTMODE_CHOICE_ENUM)liblte_bits_2_value(ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_MDTMODE_CHOICE_IMMEDIATEMDT) {
      if(liblte_s1ap_unpack_immediatemdt(ptr, &ie->choice.immediateMDT) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_MDTMODE_CHOICE_LOGGEDMDT) {
      if(liblte_s1ap_unpack_loggedmdt(ptr, &ie->choice.loggedMDT) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SourceeNB_ToTargeteNB_TransparentContainer SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_sourceenb_totargetenb_transparentcontainer(
  LIBLTE_S1AP_SOURCEENB_TOTARGETENB_TRANSPARENTCONTAINER_STRUCT       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SourceeNB_ToTargeteNB_TransparentContainer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->e_RABInformationList_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->subscriberProfileIDforRFP_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_rrc_container(&ie->rRC_Container, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->e_RABInformationList_present) {
      if(liblte_s1ap_pack_e_rabinformationlist(&ie->e_RABInformationList, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(liblte_s1ap_pack_eutran_cgi(&ie->targetCell_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->subscriberProfileIDforRFP_present) {
      if(liblte_s1ap_pack_subscriberprofileidforrfp(&ie->subscriberProfileIDforRFP, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(liblte_s1ap_pack_ue_historyinformation(&ie->uE_HistoryInformation, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_sourceenb_totargetenb_transparentcontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SOURCEENB_TOTARGETENB_TRANSPARENTCONTAINER_STRUCT       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SourceeNB_ToTargeteNB_TransparentContainer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->e_RABInformationList_present = liblte_bits_2_value(ptr, 1);
    ie->subscriberProfileIDforRFP_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_rrc_container(ptr, &ie->rRC_Container) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->e_RABInformationList_present) {
      if(liblte_s1ap_unpack_e_rabinformationlist(ptr, &ie->e_RABInformationList) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(liblte_s1ap_unpack_eutran_cgi(ptr, &ie->targetCell_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->subscriberProfileIDforRFP_present) {
      if(liblte_s1ap_unpack_subscriberprofileidforrfp(ptr, &ie->subscriberProfileIDforRFP) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(liblte_s1ap_unpack_ue_historyinformation(ptr, &ie->uE_HistoryInformation) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE EmergencyAreaID_Broadcast DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_emergencyareaid_broadcast(
  LIBLTE_S1AP_EMERGENCYAREAID_BROADCAST_STRUCT                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("EmergencyAreaID_Broadcast pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_emergencyareaid_broadcast_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_emergencyareaid_broadcast(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_EMERGENCYAREAID_BROADCAST_STRUCT                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("EmergencyAreaID_Broadcast unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_emergencyareaid_broadcast_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE MDT_Configuration SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mdt_configuration(
  LIBLTE_S1AP_MDT_CONFIGURATION_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("MDT_Configuration error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_mdt_activation(&ie->mdt_Activation, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_areascopeofmdt(&ie->areaScopeOfMDT, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_mdtmode(&ie->mDTMode, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mdt_configuration(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MDT_CONFIGURATION_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("MDT_Configuration error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_mdt_activation(ptr, &ie->mdt_Activation) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_areascopeofmdt(ptr, &ie->areaScopeOfMDT) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_mdtmode(ptr, &ie->mDTMode) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAI_Cancelled DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:65535
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tai_cancelled(
  LIBLTE_S1AP_TAI_CANCELLED_STRUCT                                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("TAI_Cancelled pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 16);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_tai_cancelled_item(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tai_cancelled(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAI_CANCELLED_STRUCT                                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 16) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("TAI_Cancelled unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_tai_cancelled_item(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE BroadcastCancelledAreaList CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_broadcastcancelledarealist(
  LIBLTE_S1AP_BROADCASTCANCELLEDAREALIST_STRUCT                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("BroadcastCancelledAreaList error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_BROADCASTCANCELLEDAREALIST_CHOICE_CELLID_CANCELLED) {
      if(liblte_s1ap_pack_cellid_cancelled(&ie->choice.cellID_Cancelled, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_BROADCASTCANCELLEDAREALIST_CHOICE_TAI_CANCELLED) {
      if(liblte_s1ap_pack_tai_cancelled(&ie->choice.tAI_Cancelled, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_BROADCASTCANCELLEDAREALIST_CHOICE_EMERGENCYAREAID_CANCELLED) {
      if(liblte_s1ap_pack_emergencyareaid_cancelled(&ie->choice.emergencyAreaID_Cancelled, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_broadcastcancelledarealist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_BROADCASTCANCELLEDAREALIST_STRUCT                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("BroadcastCancelledAreaList error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_BROADCASTCANCELLEDAREALIST_CHOICE_ENUM)liblte_bits_2_value(ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_BROADCASTCANCELLEDAREALIST_CHOICE_CELLID_CANCELLED) {
      if(liblte_s1ap_unpack_cellid_cancelled(ptr, &ie->choice.cellID_Cancelled) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_BROADCASTCANCELLEDAREALIST_CHOICE_TAI_CANCELLED) {
      if(liblte_s1ap_unpack_tai_cancelled(ptr, &ie->choice.tAI_Cancelled) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_BROADCASTCANCELLEDAREALIST_CHOICE_EMERGENCYAREAID_CANCELLED) {
      if(liblte_s1ap_unpack_emergencyareaid_cancelled(ptr, &ie->choice.emergencyAreaID_Cancelled) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ENB_StatusTransfer_TransparentContainer SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enb_statustransfer_transparentcontainer(
  LIBLTE_S1AP_ENB_STATUSTRANSFER_TRANSPARENTCONTAINER_STRUCT         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ENB_StatusTransfer_TransparentContainer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_bearers_subjecttostatustransferlist(&ie->bearers_SubjectToStatusTransferList, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enb_statustransfer_transparentcontainer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_ENB_STATUSTRANSFER_TRANSPARENTCONTAINER_STRUCT         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ENB_StatusTransfer_TransparentContainer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_bearers_subjecttostatustransferlist(ptr, &ie->bearers_SubjectToStatusTransferList) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TraceActivation SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_traceactivation(
  LIBLTE_S1AP_TRACEACTIVATION_STRUCT                                 *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TraceActivation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_utran_trace_id(&ie->e_UTRAN_Trace_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_interfacestotrace(&ie->interfacesToTrace, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_tracedepth(&ie->traceDepth, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_transportlayeraddress(&ie->traceCollectionEntityIPAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_traceactivation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TRACEACTIVATION_STRUCT                                 *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TraceActivation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_utran_trace_id(ptr, &ie->e_UTRAN_Trace_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_interfacestotrace(ptr, &ie->interfacesToTrace) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_tracedepth(ptr, &ie->traceDepth) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->traceCollectionEntityIPAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE BroadcastCompletedAreaList CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_broadcastcompletedarealist(
  LIBLTE_S1AP_BROADCASTCOMPLETEDAREALIST_STRUCT                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("BroadcastCompletedAreaList error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_BROADCASTCOMPLETEDAREALIST_CHOICE_CELLID_BROADCAST) {
      if(liblte_s1ap_pack_cellid_broadcast(&ie->choice.cellID_Broadcast, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_BROADCASTCOMPLETEDAREALIST_CHOICE_TAI_BROADCAST) {
      if(liblte_s1ap_pack_tai_broadcast(&ie->choice.tAI_Broadcast, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_BROADCASTCOMPLETEDAREALIST_CHOICE_EMERGENCYAREAID_BROADCAST) {
      if(liblte_s1ap_pack_emergencyareaid_broadcast(&ie->choice.emergencyAreaID_Broadcast, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_broadcastcompletedarealist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_BROADCASTCOMPLETEDAREALIST_STRUCT                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("BroadcastCompletedAreaList error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_BROADCASTCOMPLETEDAREALIST_CHOICE_ENUM)liblte_bits_2_value(ptr, 2);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_BROADCASTCOMPLETEDAREALIST_CHOICE_CELLID_BROADCAST) {
      if(liblte_s1ap_unpack_cellid_broadcast(ptr, &ie->choice.cellID_Broadcast) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_BROADCASTCOMPLETEDAREALIST_CHOICE_TAI_BROADCAST) {
      if(liblte_s1ap_unpack_tai_broadcast(ptr, &ie->choice.tAI_Broadcast) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_BROADCASTCOMPLETEDAREALIST_CHOICE_EMERGENCYAREAID_BROADCAST) {
      if(liblte_s1ap_unpack_emergencyareaid_broadcast(ptr, &ie->choice.emergencyAreaID_Broadcast) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SONInformation CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_soninformation(
  LIBLTE_S1AP_SONINFORMATION_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SONInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_SONINFORMATION_CHOICE_SONINFORMATIONREQUEST) {
      if(liblte_s1ap_pack_soninformationrequest(&ie->choice.sONInformationRequest, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_SONINFORMATION_CHOICE_SONINFORMATIONREPLY) {
      if(liblte_s1ap_pack_soninformationreply(&ie->choice.sONInformationReply, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_soninformation(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SONINFORMATION_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SONInformation error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_SONINFORMATION_CHOICE_ENUM)liblte_bits_2_value(ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_SONINFORMATION_CHOICE_SONINFORMATIONREQUEST) {
      if(liblte_s1ap_unpack_soninformationrequest(ptr, &ie->choice.sONInformationRequest) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_SONINFORMATION_CHOICE_SONINFORMATIONREPLY) {
      if(liblte_s1ap_unpack_soninformationreply(ptr, &ie->choice.sONInformationReply) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE SONConfigurationTransfer SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_sonconfigurationtransfer(
  LIBLTE_S1AP_SONCONFIGURATIONTRANSFER_STRUCT                        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("SONConfigurationTransfer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_targetenb_id(&ie->targeteNB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_sourceenb_id(&ie->sourceeNB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_soninformation(&ie->sONInformation, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_sonconfigurationtransfer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_SONCONFIGURATIONTRANSFER_STRUCT                        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("SONConfigurationTransfer error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_targetenb_id(ptr, &ie->targeteNB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_sourceenb_id(ptr, &ie->sourceeNB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_soninformation(ptr, &ie->sONInformation) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ResetAll ENUMERATED
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_resetall(
  LIBLTE_S1AP_RESETALL_ENUM_EXT                                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ResetAll error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Enum
    liblte_value_2_bits(ie->e, ptr, 0);
    liblte_align_up_zero(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_resetall(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RESETALL_ENUM_EXT                                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ResetAll error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Enum
    ie->e = (LIBLTE_S1AP_RESETALL_ENUM)liblte_bits_2_value(ptr, 0);
    liblte_align_up(ptr, 8);
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE Inter_SystemInformationTransferType CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_inter_systeminformationtransfertype(
  LIBLTE_S1AP_INTER_SYSTEMINFORMATIONTRANSFERTYPE_STRUCT             *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("Inter_SystemInformationTransferType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 0);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_INTER_SYSTEMINFORMATIONTRANSFERTYPE_CHOICE_RIMTRANSFER) {
      if(liblte_s1ap_pack_rimtransfer(&ie->choice.rIMTransfer, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_inter_systeminformationtransfertype(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_INTER_SYSTEMINFORMATIONTRANSFERTYPE_STRUCT             *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("Inter_SystemInformationTransferType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_INTER_SYSTEMINFORMATIONTRANSFERTYPE_CHOICE_ENUM)liblte_bits_2_value(ptr, 0);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_INTER_SYSTEMINFORMATIONTRANSFERTYPE_CHOICE_RIMTRANSFER) {
      if(liblte_s1ap_unpack_rimtransfer(ptr, &ie->choice.rIMTransfer) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RAB_IE_ContainerPairList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rab_ie_containerpairlist(
  LIBLTE_S1AP_E_RAB_IE_CONTAINERPAIRLIST_STRUCT                      *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RAB_IE_ContainerPairList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_pack_protocolie_containerpair(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rab_ie_containerpairlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RAB_IE_CONTAINERPAIRLIST_STRUCT                      *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RAB_IE_ContainerPairList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_containerpair(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABDataForwardingItem SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabdataforwardingitem(
  LIBLTE_S1AP_E_RABDATAFORWARDINGITEM_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABDataForwardingItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->dL_transportLayerAddress_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->dL_gTP_TEID_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->uL_TransportLayerAddress_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->uL_GTP_TEID_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->dL_transportLayerAddress_present) {
      if(liblte_s1ap_pack_transportlayeraddress(&ie->dL_transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->dL_gTP_TEID_present) {
      if(liblte_s1ap_pack_gtp_teid(&ie->dL_gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->uL_TransportLayerAddress_present) {
      if(liblte_s1ap_pack_transportlayeraddress(&ie->uL_TransportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->uL_GTP_TEID_present) {
      if(liblte_s1ap_pack_gtp_teid(&ie->uL_GTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabdataforwardingitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABDATAFORWARDINGITEM_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABDataForwardingItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->dL_transportLayerAddress_present = liblte_bits_2_value(ptr, 1);
    ie->dL_gTP_TEID_present = liblte_bits_2_value(ptr, 1);
    ie->uL_TransportLayerAddress_present = liblte_bits_2_value(ptr, 1);
    ie->uL_GTP_TEID_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->dL_transportLayerAddress_present) {
      if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->dL_transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->dL_gTP_TEID_present) {
      if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->dL_gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->uL_TransportLayerAddress_present) {
      if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->uL_TransportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->uL_GTP_TEID_present) {
      if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->uL_GTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABToBeSetupItemHOReq SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemhoreq(
  LIBLTE_S1AP_E_RABTOBESETUPITEMHOREQ_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSetupItemHOReq error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_gtp_teid(&ie->gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_e_rablevelqosparameters(&ie->e_RABlevelQosParameters, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetupitemhoreq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESETUPITEMHOREQ_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSetupItemHOReq error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_e_rablevelqosparameters(ptr, &ie->e_RABlevelQosParameters) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABAdmittedItem SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabadmitteditem(
  LIBLTE_S1AP_E_RABADMITTEDITEM_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABAdmittedItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->dL_transportLayerAddress_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->dL_gTP_TEID_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->uL_TransportLayerAddress_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->uL_GTP_TEID_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_gtp_teid(&ie->gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->dL_transportLayerAddress_present) {
      if(liblte_s1ap_pack_transportlayeraddress(&ie->dL_transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->dL_gTP_TEID_present) {
      if(liblte_s1ap_pack_gtp_teid(&ie->dL_gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->uL_TransportLayerAddress_present) {
      if(liblte_s1ap_pack_transportlayeraddress(&ie->uL_TransportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->uL_GTP_TEID_present) {
      if(liblte_s1ap_pack_gtp_teid(&ie->uL_GTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabadmitteditem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABADMITTEDITEM_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABAdmittedItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->dL_transportLayerAddress_present = liblte_bits_2_value(ptr, 1);
    ie->dL_gTP_TEID_present = liblte_bits_2_value(ptr, 1);
    ie->uL_TransportLayerAddress_present = liblte_bits_2_value(ptr, 1);
    ie->uL_GTP_TEID_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->dL_transportLayerAddress_present) {
      if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->dL_transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->dL_gTP_TEID_present) {
      if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->dL_gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->uL_TransportLayerAddress_present) {
      if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->uL_TransportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->uL_GTP_TEID_present) {
      if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->uL_GTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABFailedToSetupItemHOReqAck SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack(
  LIBLTE_S1AP_E_RABFAILEDTOSETUPITEMHOREQACK_STRUCT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABFailedToSetupItemHOReqAck error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_cause(&ie->cause, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabfailedtosetupitemhoreqack(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABFAILEDTOSETUPITEMHOREQACK_STRUCT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABFailedToSetupItemHOReqAck error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_cause(ptr, &ie->cause) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABToBeSwitchedDLItem SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitcheddlitem(
  LIBLTE_S1AP_E_RABTOBESWITCHEDDLITEM_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSwitchedDLItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_gtp_teid(&ie->gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobeswitcheddlitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESWITCHEDDLITEM_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSwitchedDLItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABToBeSwitchedULItem SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitchedulitem(
  LIBLTE_S1AP_E_RABTOBESWITCHEDULITEM_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSwitchedULItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_gtp_teid(&ie->gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobeswitchedulitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESWITCHEDULITEM_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSwitchedULItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABToBeSetupItemBearerSUReq SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitembearersureq(
  LIBLTE_S1AP_E_RABTOBESETUPITEMBEARERSUREQ_STRUCT                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSetupItemBearerSUReq error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_e_rablevelqosparameters(&ie->e_RABlevelQoSParameters, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_gtp_teid(&ie->gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_nas_pdu(&ie->nAS_PDU, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetupitembearersureq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESETUPITEMBEARERSUREQ_STRUCT                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSetupItemBearerSUReq error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_e_rablevelqosparameters(ptr, &ie->e_RABlevelQoSParameters) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_nas_pdu(ptr, &ie->nAS_PDU) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABSetupItemBearerSURes SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitembearersures(
  LIBLTE_S1AP_E_RABSETUPITEMBEARERSURES_STRUCT                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABSetupItemBearerSURes error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_gtp_teid(&ie->gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetupitembearersures(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABSETUPITEMBEARERSURES_STRUCT                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABSetupItemBearerSURes error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABToBeModifiedItemBearerModReq SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifieditembearermodreq(
  LIBLTE_S1AP_E_RABTOBEMODIFIEDITEMBEARERMODREQ_STRUCT               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeModifiedItemBearerModReq error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_e_rablevelqosparameters(&ie->e_RABLevelQoSParameters, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_nas_pdu(&ie->nAS_PDU, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobemodifieditembearermodreq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBEMODIFIEDITEMBEARERMODREQ_STRUCT               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeModifiedItemBearerModReq error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_e_rablevelqosparameters(ptr, &ie->e_RABLevelQoSParameters) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_nas_pdu(ptr, &ie->nAS_PDU) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABModifyItemBearerModRes SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyitembearermodres(
  LIBLTE_S1AP_E_RABMODIFYITEMBEARERMODRES_STRUCT                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABModifyItemBearerModRes error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabmodifyitembearermodres(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABMODIFYITEMBEARERMODRES_STRUCT                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABModifyItemBearerModRes error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABReleaseItemBearerRelComp SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseitembearerrelcomp(
  LIBLTE_S1AP_E_RABRELEASEITEMBEARERRELCOMP_STRUCT                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABReleaseItemBearerRelComp error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabreleaseitembearerrelcomp(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABRELEASEITEMBEARERRELCOMP_STRUCT                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABReleaseItemBearerRelComp error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABToBeSetupItemCtxtSUReq SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemctxtsureq(
  LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSetupItemCtxtSUReq error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->nAS_PDU_present?1:0, ptr, 1);
    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_e_rablevelqosparameters(&ie->e_RABlevelQoSParameters, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_gtp_teid(&ie->gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->nAS_PDU_present) {
      if(liblte_s1ap_pack_nas_pdu(&ie->nAS_PDU, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetupitemctxtsureq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABToBeSetupItemCtxtSUReq error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->nAS_PDU_present = liblte_bits_2_value(ptr, 1);
    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_e_rablevelqosparameters(ptr, &ie->e_RABlevelQoSParameters) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->nAS_PDU_present) {
      if(liblte_s1ap_unpack_nas_pdu(ptr, &ie->nAS_PDU) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE E_RABSetupItemCtxtSURes SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitemctxtsures(
  LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABSetupItemCtxtSURes error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_e_rab_id(&ie->e_RAB_ID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_transportlayeraddress(&ie->transportLayerAddress, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(liblte_s1ap_pack_gtp_teid(&ie->gTP_TEID, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetupitemctxtsures(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABSETUPITEMCTXTSURES_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("E_RABSetupItemCtxtSURes error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_e_rab_id(ptr, &ie->e_RAB_ID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_transportlayeraddress(ptr, &ie->transportLayerAddress) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(liblte_s1ap_unpack_gtp_teid(ptr, &ie->gTP_TEID) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE TAIItem SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_taiitem(
  LIBLTE_S1AP_TAIITEM_STRUCT                                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAIItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1);

    if(liblte_s1ap_pack_tai(&ie->tAI, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_taiitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAIITEM_STRUCT                                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("TAIItem error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1);

    if(liblte_s1ap_unpack_tai(ptr, &ie->tAI) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    if(ie->iE_Extensions_present) {
      if(liblte_s1ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List UE_associatedLogicalS1_ConnectionListRes DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionlistres(
  LIBLTE_S1AP_UE_ASSOCIATEDLOGICALS1_CONNECTIONLISTRES_STRUCT        *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("UE_associatedLogicalS1_ConnectionListRes pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_associatedlogicals1_connectionlistres(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UE_ASSOCIATEDLOGICALS1_CONNECTIONLISTRES_STRUCT        *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("UE_associatedLogicalS1_ConnectionListRes unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_ue_associatedlogicals1_connectionitem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List UE_associatedLogicalS1_ConnectionListResAck DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionlistresack(
  LIBLTE_S1AP_UE_ASSOCIATEDLOGICALS1_CONNECTIONLISTRESACK_STRUCT       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("UE_associatedLogicalS1_ConnectionListResAck pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_associatedlogicals1_connectionlistresack(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_UE_ASSOCIATEDLOGICALS1_CONNECTIONLISTRESACK_STRUCT       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("UE_associatedLogicalS1_ConnectionListResAck unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_ue_associatedlogicals1_connectionitem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE PrivateMessage SEQUENCE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_privatemessage(
  LIBLTE_S1AP_PRIVATEMESSAGE_STRUCT                                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("PrivateMessage error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }


    if(liblte_s1ap_pack_privateie_container(&ie->privateIEs, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_privatemessage(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_PRIVATEMESSAGE_STRUCT                                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("PrivateMessage error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }


    if(liblte_s1ap_unpack_privateie_container(ptr, &ie->privateIEs) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE ResetType CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_resettype(
  LIBLTE_S1AP_RESETTYPE_STRUCT                                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    liblte_value_2_bits(ie->ext?1:0, ptr, 1);
    if(ie->ext) {
      liblte_log_print("ResetType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // Choice type
    liblte_value_2_bits(ie->choice_type, ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_RESETTYPE_CHOICE_S1_INTERFACE) {
      if(liblte_s1ap_pack_resetall(&ie->choice.s1_Interface, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_RESETTYPE_CHOICE_PARTOFS1_INTERFACE) {
      if(liblte_s1ap_pack_ue_associatedlogicals1_connectionlistres(&ie->choice.partOfS1_Interface, ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_resettype(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_RESETTYPE_STRUCT                                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    // Extension
    ie->ext  = liblte_bits_2_value(ptr, 1);
    if(ie->ext) {
      liblte_log_print("ResetType error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // Choice type
    ie->choice_type = (LIBLTE_S1AP_RESETTYPE_CHOICE_ENUM)liblte_bits_2_value(ptr, 1);

       // Choice
 if(ie->choice_type == LIBLTE_S1AP_RESETTYPE_CHOICE_S1_INTERFACE) {
      if(liblte_s1ap_unpack_resetall(ptr, &ie->choice.s1_Interface) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } else if(ie->choice_type == LIBLTE_S1AP_RESETTYPE_CHOICE_PARTOFS1_INTERFACE) {
      if(liblte_s1ap_unpack_ue_associatedlogicals1_connectionlistres(ptr, &ie->choice.partOfS1_Interface) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_DECODE_FAIL;
    }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABSubjecttoDataForwardingList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsubjecttodataforwardinglist(
  LIBLTE_S1AP_E_RABSUBJECTTODATAFORWARDINGLIST_STRUCT                *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABSubjecttoDataForwardingList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabdataforwardingitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABDATAFORWARDINGITEM,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsubjecttodataforwardinglist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABSUBJECTTODATAFORWARDINGLIST_STRUCT                *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABSubjecttoDataForwardingList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABDATAFORWARDINGITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabdataforwardingitem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABToBeSetupListHOReq DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetuplisthoreq(
  LIBLTE_S1AP_E_RABTOBESETUPLISTHOREQ_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSetupListHOReq pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabtobesetupitemhoreq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMHOREQ,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetuplisthoreq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESETUPLISTHOREQ_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSetupListHOReq unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMHOREQ != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabtobesetupitemhoreq(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABAdmittedList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabadmittedlist(
  LIBLTE_S1AP_E_RABADMITTEDLIST_STRUCT                               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABAdmittedList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabadmitteditem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABADMITTEDITEM,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabadmittedlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABADMITTEDLIST_STRUCT                               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABAdmittedList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABADMITTEDITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabadmitteditem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABToBeSwitchedDLList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitcheddllist(
  LIBLTE_S1AP_E_RABTOBESWITCHEDDLLIST_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSwitchedDLList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabtobeswitcheddlitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDDLITEM,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobeswitcheddllist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESWITCHEDDLLIST_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSwitchedDLList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDDLITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabtobeswitcheddlitem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABToBeSwitchedULList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitchedullist(
  LIBLTE_S1AP_E_RABTOBESWITCHEDULLIST_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSwitchedULList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabtobeswitchedulitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDULITEM,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobeswitchedullist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESWITCHEDULLIST_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSwitchedULList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDULITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabtobeswitchedulitem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABToBeSetupListBearerSUReq DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetuplistbearersureq(
  LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSetupListBearerSUReq pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabtobesetupitembearersureq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMBEARERSUREQ,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetuplistbearersureq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSetupListBearerSUReq unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMBEARERSUREQ != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabtobesetupitembearersureq(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABSetupListBearerSURes DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuplistbearersures(
  LIBLTE_S1AP_E_RABSETUPLISTBEARERSURES_STRUCT                       *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABSetupListBearerSURes pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabsetupitembearersures(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABSETUPITEMBEARERSURES,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetuplistbearersures(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABSETUPLISTBEARERSURES_STRUCT                       *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABSetupListBearerSURes unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABSETUPITEMBEARERSURES != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabsetupitembearersures(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABToBeModifiedListBearerModReq DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifiedlistbearermodreq(
  LIBLTE_S1AP_E_RABTOBEMODIFIEDLISTBEARERMODREQ_STRUCT               *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeModifiedListBearerModReq pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabtobemodifieditembearermodreq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABTOBEMODIFIEDITEMBEARERMODREQ,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobemodifiedlistbearermodreq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBEMODIFIEDLISTBEARERMODREQ_STRUCT               *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeModifiedListBearerModReq unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBEMODIFIEDITEMBEARERMODREQ != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabtobemodifieditembearermodreq(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABModifyListBearerModRes DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifylistbearermodres(
  LIBLTE_S1AP_E_RABMODIFYLISTBEARERMODRES_STRUCT                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABModifyListBearerModRes pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabmodifyitembearermodres(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABMODIFYITEMBEARERMODRES,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabmodifylistbearermodres(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABMODIFYLISTBEARERMODRES_STRUCT                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABModifyListBearerModRes unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABMODIFYITEMBEARERMODRES != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabmodifyitembearermodres(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABReleaseListBearerRelComp DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaselistbearerrelcomp(
  LIBLTE_S1AP_E_RABRELEASELISTBEARERRELCOMP_STRUCT                   *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABReleaseListBearerRelComp pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabreleaseitembearerrelcomp(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABRELEASEITEMBEARERRELCOMP,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabreleaselistbearerrelcomp(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABRELEASELISTBEARERRELCOMP_STRUCT                   *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABReleaseListBearerRelComp unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABRELEASEITEMBEARERRELCOMP != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabreleaseitembearerrelcomp(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABToBeSetupListCtxtSUReq DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetuplistctxtsureq(
  LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT                     *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSetupListCtxtSUReq pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabtobesetupitemctxtsureq(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMCTXTSUREQ,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetuplistctxtsureq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT                     *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABToBeSetupListCtxtSUReq unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMCTXTSUREQ != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabtobesetupitemctxtsureq(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABSetupListCtxtSURes DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuplistctxtsures(
  LIBLTE_S1AP_E_RABSETUPLISTCTXTSURES_STRUCT                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABSetupListCtxtSURes pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabsetupitemctxtsures(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABSETUPITEMCTXTSURES,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetuplistctxtsures(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABSETUPLISTCTXTSURES_STRUCT                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABSetupListCtxtSURes unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABSETUPITEMCTXTSURES != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabsetupitemctxtsures(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List TAIList DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tailist(
  LIBLTE_S1AP_TAILIST_STRUCT                                         *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("TAIList pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_taiitem(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TAIITEM,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tailist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_TAILIST_STRUCT                                         *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("TAIList unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_TAIITEM != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_taiitem(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Container List E_RABFailedtoSetupListHOReqAck DYNAMIC SEQUENCE OF
********************************************************************************/
// lb:1, ub:256
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabfailedtosetuplisthoreqack(
  LIBLTE_S1AP_E_RABFAILEDTOSETUPLISTHOREQACK_STRUCT                  *ie,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    if(ie->len > 32) {
      liblte_log_print("E_RABFailedtoSetupListHOReqAck pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    // Length
    liblte_value_2_bits(ie->len-1, ptr, 8);
    liblte_align_up_zero(ptr, 8);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack(&ie->buffer[i], &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPITEMHOREQACK,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabfailedtosetuplisthoreqack(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_E_RABFAILEDTOSETUPLISTHOREQACK_STRUCT                  *ie)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(ie  != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;

    // Length
    ie->len = liblte_bits_2_value(ptr, 8) + 1;
    liblte_align_up(ptr, 8);
    if(ie->len > 32) {
      liblte_log_print("E_RABFailedtoSetupListHOReqAck unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len);
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    uint32_t i;
    for(i=0;i<ie->len;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPITEMHOREQACK != ie_id) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(liblte_s1ap_unpack_e_rabfailedtosetupitemhoreqack(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message AllocationAndRetentionPriority_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_allocationandretentionpriority_ext(
  LIBLTE_S1AP_MESSAGE_ALLOCATIONANDRETENTIONPRIORITY_EXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("AllocationAndRetentionPriority-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_allocationandretentionpriority_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ALLOCATIONANDRETENTIONPRIORITY_EXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("AllocationAndRetentionPriority-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CancelledCellinEAI_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cancelledcellineai_item_ext(
  LIBLTE_S1AP_MESSAGE_CANCELLEDCELLINEAI_ITEM_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CancelledCellinEAI-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cancelledcellineai_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CANCELLEDCELLINEAI_ITEM_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CancelledCellinEAI-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CancelledCellinTAI_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cancelledcellintai_item_ext(
  LIBLTE_S1AP_MESSAGE_CANCELLEDCELLINTAI_ITEM_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CancelledCellinTAI-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cancelledcellintai_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CANCELLEDCELLINTAI_ITEM_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CancelledCellinTAI-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CellID_Broadcast_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellid_broadcast_item_ext(
  LIBLTE_S1AP_MESSAGE_CELLID_BROADCAST_ITEM_EXT_STRUCT               *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellID-Broadcast-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellid_broadcast_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CELLID_BROADCAST_ITEM_EXT_STRUCT               *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellID-Broadcast-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CellID_Cancelled_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellid_cancelled_item_ext(
  LIBLTE_S1AP_MESSAGE_CELLID_CANCELLED_ITEM_EXT_STRUCT               *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellID-Cancelled-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellid_cancelled_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CELLID_CANCELLED_ITEM_EXT_STRUCT               *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellID-Cancelled-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CellBasedMDT_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cellbasedmdt_ext(
  LIBLTE_S1AP_MESSAGE_CELLBASEDMDT_EXT_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellBasedMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cellbasedmdt_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CELLBASEDMDT_EXT_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellBasedMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message Cdma2000OneXSRVCCInfo_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cdma2000onexsrvccinfo_ext(
  LIBLTE_S1AP_MESSAGE_CDMA2000ONEXSRVCCINFO_EXT_STRUCT               *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("Cdma2000OneXSRVCCInfo-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cdma2000onexsrvccinfo_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CDMA2000ONEXSRVCCINFO_EXT_STRUCT               *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("Cdma2000OneXSRVCCInfo-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CellType_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltype_ext(
  LIBLTE_S1AP_MESSAGE_CELLTYPE_EXT_STRUCT                            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellType-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_celltype_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CELLTYPE_EXT_STRUCT                            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellType-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CGI_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_cgi_ext(
  LIBLTE_S1AP_MESSAGE_CGI_EXT_STRUCT                                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CGI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_cgi_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CGI_EXT_STRUCT                                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CGI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CSG_IdList_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_csg_idlist_item_ext(
  LIBLTE_S1AP_MESSAGE_CSG_IDLIST_ITEM_EXT_STRUCT                     *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CSG-IdList-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_csg_idlist_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CSG_IDLIST_ITEM_EXT_STRUCT                     *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CSG-IdList-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message COUNTvalue_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_countvalue_ext(
  LIBLTE_S1AP_MESSAGE_COUNTVALUE_EXT_STRUCT                          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("COUNTvalue-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_countvalue_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_COUNTVALUE_EXT_STRUCT                          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("COUNTvalue-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message COUNTValueExtended_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_countvalueextended_ext(
  LIBLTE_S1AP_MESSAGE_COUNTVALUEEXTENDED_EXT_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("COUNTValueExtended-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_countvalueextended_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_COUNTVALUEEXTENDED_EXT_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("COUNTValueExtended-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CriticalityDiagnostics_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_criticalitydiagnostics_ext(
  LIBLTE_S1AP_MESSAGE_CRITICALITYDIAGNOSTICS_EXT_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CriticalityDiagnostics-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_criticalitydiagnostics_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CRITICALITYDIAGNOSTICS_EXT_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CriticalityDiagnostics-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CriticalityDiagnostics_IE_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_criticalitydiagnostics_ie_item_ext(
  LIBLTE_S1AP_MESSAGE_CRITICALITYDIAGNOSTICS_IE_ITEM_EXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CriticalityDiagnostics-IE-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_criticalitydiagnostics_ie_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CRITICALITYDIAGNOSTICS_IE_ITEM_EXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CriticalityDiagnostics-IE-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message EmergencyAreaID_Broadcast_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_emergencyareaid_broadcast_item_ext(
  LIBLTE_S1AP_MESSAGE_EMERGENCYAREAID_BROADCAST_ITEM_EXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("EmergencyAreaID-Broadcast-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_emergencyareaid_broadcast_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_EMERGENCYAREAID_BROADCAST_ITEM_EXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("EmergencyAreaID-Broadcast-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message EmergencyAreaID_Cancelled_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_emergencyareaid_cancelled_item_ext(
  LIBLTE_S1AP_MESSAGE_EMERGENCYAREAID_CANCELLED_ITEM_EXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("EmergencyAreaID-Cancelled-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_emergencyareaid_cancelled_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_EMERGENCYAREAID_CANCELLED_ITEM_EXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("EmergencyAreaID-Cancelled-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CompletedCellinEAI_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_completedcellineai_item_ext(
  LIBLTE_S1AP_MESSAGE_COMPLETEDCELLINEAI_ITEM_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CompletedCellinEAI-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_completedcellineai_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_COMPLETEDCELLINEAI_ITEM_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CompletedCellinEAI-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message GERAN_Cell_ID_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_geran_cell_id_ext(
  LIBLTE_S1AP_MESSAGE_GERAN_CELL_ID_EXT_STRUCT                       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("GERAN-Cell-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_geran_cell_id_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_GERAN_CELL_ID_EXT_STRUCT                       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("GERAN-Cell-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message GlobalENB_ID_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_globalenb_id_ext(
  LIBLTE_S1AP_MESSAGE_GLOBALENB_ID_EXT_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("GlobalENB-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_globalenb_id_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_GLOBALENB_ID_EXT_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("GlobalENB-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ENB_StatusTransfer_TransparentContainer_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enb_statustransfer_transparentcontainer_ext(
  LIBLTE_S1AP_MESSAGE_ENB_STATUSTRANSFER_TRANSPARENTCONTAINER_EXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENB-StatusTransfer-TransparentContainer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enb_statustransfer_transparentcontainer_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ENB_STATUSTRANSFER_TRANSPARENTCONTAINER_EXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENB-StatusTransfer-TransparentContainer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABInformationListItem_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabinformationlistitem_ext(
  LIBLTE_S1AP_MESSAGE_E_RABINFORMATIONLISTITEM_EXT_STRUCT            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABInformationListItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabinformationlistitem_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABINFORMATIONLISTITEM_EXT_STRUCT            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABInformationListItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABItem_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabitem_ext(
  LIBLTE_S1AP_MESSAGE_E_RABITEM_EXT_STRUCT                           *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabitem_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABITEM_EXT_STRUCT                           *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABQoSParameters_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabqosparameters_ext(
  LIBLTE_S1AP_MESSAGE_E_RABQOSPARAMETERS_EXT_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABQoSParameters-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabqosparameters_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABQOSPARAMETERS_EXT_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABQoSParameters-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message EUTRAN_CGI_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_eutran_cgi_ext(
  LIBLTE_S1AP_MESSAGE_EUTRAN_CGI_EXT_STRUCT                          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("EUTRAN-CGI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_eutran_cgi_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_EUTRAN_CGI_EXT_STRUCT                          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("EUTRAN-CGI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ForbiddenTAs_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_forbiddentas_item_ext(
  LIBLTE_S1AP_MESSAGE_FORBIDDENTAS_ITEM_EXT_STRUCT                   *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ForbiddenTAs-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_forbiddentas_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_FORBIDDENTAS_ITEM_EXT_STRUCT                   *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ForbiddenTAs-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ForbiddenLAs_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_forbiddenlas_item_ext(
  LIBLTE_S1AP_MESSAGE_FORBIDDENLAS_ITEM_EXT_STRUCT                   *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ForbiddenLAs-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_forbiddenlas_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_FORBIDDENLAS_ITEM_EXT_STRUCT                   *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ForbiddenLAs-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message GBR_QosInformation_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_gbr_qosinformation_ext(
  LIBLTE_S1AP_MESSAGE_GBR_QOSINFORMATION_EXT_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("GBR-QosInformation-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_gbr_qosinformation_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_GBR_QOSINFORMATION_EXT_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("GBR-QosInformation-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message GUMMEI_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_gummei_ext(
  LIBLTE_S1AP_MESSAGE_GUMMEI_EXT_STRUCT                              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("GUMMEI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_gummei_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_GUMMEI_EXT_STRUCT                              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("GUMMEI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverRestrictionList_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrestrictionlist_ext(
  LIBLTE_S1AP_MESSAGE_HANDOVERRESTRICTIONLIST_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverRestrictionList-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handoverrestrictionlist_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERRESTRICTIONLIST_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverRestrictionList-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message LAI_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lai_ext(
  LIBLTE_S1AP_MESSAGE_LAI_EXT_STRUCT                                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LAI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lai_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_LAI_EXT_STRUCT                                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LAI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message LoggedMDT_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_loggedmdt_ext(
  LIBLTE_S1AP_MESSAGE_LOGGEDMDT_EXT_STRUCT                           *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LoggedMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_loggedmdt_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_LOGGEDMDT_EXT_STRUCT                           *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LoggedMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message M3Configuration_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m3configuration_ext(
  LIBLTE_S1AP_MESSAGE_M3CONFIGURATION_EXT_STRUCT                     *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M3Configuration-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m3configuration_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_M3CONFIGURATION_EXT_STRUCT                     *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M3Configuration-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message M4Configuration_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m4configuration_ext(
  LIBLTE_S1AP_MESSAGE_M4CONFIGURATION_EXT_STRUCT                     *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M4Configuration-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m4configuration_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_M4CONFIGURATION_EXT_STRUCT                     *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M4Configuration-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message M5Configuration_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m5configuration_ext(
  LIBLTE_S1AP_MESSAGE_M5CONFIGURATION_EXT_STRUCT                     *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M5Configuration-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m5configuration_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_M5CONFIGURATION_EXT_STRUCT                     *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M5Configuration-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message M1PeriodicReporting_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m1periodicreporting_ext(
  LIBLTE_S1AP_MESSAGE_M1PERIODICREPORTING_EXT_STRUCT                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M1PeriodicReporting-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m1periodicreporting_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_M1PERIODICREPORTING_EXT_STRUCT                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M1PeriodicReporting-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message RequestType_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_requesttype_ext(
  LIBLTE_S1AP_MESSAGE_REQUESTTYPE_EXT_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("RequestType-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_requesttype_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_REQUESTTYPE_EXT_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("RequestType-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message RIMTransfer_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_rimtransfer_ext(
  LIBLTE_S1AP_MESSAGE_RIMTRANSFER_EXT_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("RIMTransfer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_rimtransfer_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_RIMTRANSFER_EXT_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("RIMTransfer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message SecurityContext_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_securitycontext_ext(
  LIBLTE_S1AP_MESSAGE_SECURITYCONTEXT_EXT_STRUCT                     *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SecurityContext-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_securitycontext_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_SECURITYCONTEXT_EXT_STRUCT                     *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SecurityContext-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message SourceeNB_ID_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_sourceenb_id_ext(
  LIBLTE_S1AP_MESSAGE_SOURCEENB_ID_EXT_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SourceeNB-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_sourceenb_id_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_SOURCEENB_ID_EXT_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SourceeNB-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ServedGUMMEIsItem_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_servedgummeisitem_ext(
  LIBLTE_S1AP_MESSAGE_SERVEDGUMMEISITEM_EXT_STRUCT                   *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ServedGUMMEIsItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_servedgummeisitem_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_SERVEDGUMMEISITEM_EXT_STRUCT                   *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ServedGUMMEIsItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message SupportedTAs_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_supportedtas_item_ext(
  LIBLTE_S1AP_MESSAGE_SUPPORTEDTAS_ITEM_EXT_STRUCT                   *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SupportedTAs-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_supportedtas_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_SUPPORTEDTAS_ITEM_EXT_STRUCT                   *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SupportedTAs-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TimeSynchronizationInfo_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_timesynchronizationinfo_ext(
  LIBLTE_S1AP_MESSAGE_TIMESYNCHRONIZATIONINFO_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TimeSynchronizationInfo-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_timesynchronizationinfo_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TIMESYNCHRONIZATIONINFO_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TimeSynchronizationInfo-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message S_TMSI_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_s_tmsi_ext(
  LIBLTE_S1AP_MESSAGE_S_TMSI_EXT_STRUCT                              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("S-TMSI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_s_tmsi_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_S_TMSI_EXT_STRUCT                              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("S-TMSI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TAIBasedMDT_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_taibasedmdt_ext(
  LIBLTE_S1AP_MESSAGE_TAIBASEDMDT_EXT_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAIBasedMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_taibasedmdt_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TAIBASEDMDT_EXT_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAIBasedMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TAI_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tai_ext(
  LIBLTE_S1AP_MESSAGE_TAI_EXT_STRUCT                                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tai_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TAI_EXT_STRUCT                                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAI-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TAI_Broadcast_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tai_broadcast_item_ext(
  LIBLTE_S1AP_MESSAGE_TAI_BROADCAST_ITEM_EXT_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAI-Broadcast-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tai_broadcast_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TAI_BROADCAST_ITEM_EXT_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAI-Broadcast-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TAI_Cancelled_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tai_cancelled_item_ext(
  LIBLTE_S1AP_MESSAGE_TAI_CANCELLED_ITEM_EXT_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAI-Cancelled-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tai_cancelled_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TAI_CANCELLED_ITEM_EXT_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAI-Cancelled-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TABasedMDT_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tabasedmdt_ext(
  LIBLTE_S1AP_MESSAGE_TABASEDMDT_EXT_STRUCT                          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TABasedMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tabasedmdt_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TABASEDMDT_EXT_STRUCT                          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TABasedMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CompletedCellinTAI_Item_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_completedcellintai_item_ext(
  LIBLTE_S1AP_MESSAGE_COMPLETEDCELLINTAI_ITEM_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CompletedCellinTAI-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_completedcellintai_item_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_COMPLETEDCELLINTAI_ITEM_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CompletedCellinTAI-Item-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TargeteNB_ID_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_targetenb_id_ext(
  LIBLTE_S1AP_MESSAGE_TARGETENB_ID_EXT_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TargeteNB-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_targetenb_id_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TARGETENB_ID_EXT_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TargeteNB-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TargetRNC_ID_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_targetrnc_id_ext(
  LIBLTE_S1AP_MESSAGE_TARGETRNC_ID_EXT_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TargetRNC-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_targetrnc_id_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TARGETRNC_ID_EXT_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TargetRNC-ID-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TargeteNB_ToSourceeNB_TransparentContainer_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_targetenb_tosourceenb_transparentcontainer_ext(
  LIBLTE_S1AP_MESSAGE_TARGETENB_TOSOURCEENB_TRANSPARENTCONTAINER_EXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TargeteNB-ToSourceeNB-TransparentContainer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_targetenb_tosourceenb_transparentcontainer_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TARGETENB_TOSOURCEENB_TRANSPARENTCONTAINER_EXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TargeteNB-ToSourceeNB-TransparentContainer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message M1ThresholdEventA2_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_m1thresholdeventa2_ext(
  LIBLTE_S1AP_MESSAGE_M1THRESHOLDEVENTA2_EXT_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M1ThresholdEventA2-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_m1thresholdeventa2_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_M1THRESHOLDEVENTA2_EXT_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("M1ThresholdEventA2-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message Tunnel_Information_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tunnel_information_ext(
  LIBLTE_S1AP_MESSAGE_TUNNEL_INFORMATION_EXT_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("Tunnel-Information-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tunnel_information_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TUNNEL_INFORMATION_EXT_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("Tunnel-Information-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UEAggregate_MaximumBitrates_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueaggregate_maximumbitrates_ext(
  LIBLTE_S1AP_MESSAGE_UEAGGREGATE_MAXIMUMBITRATES_EXT_STRUCT         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEAggregate-MaximumBitrates-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ueaggregate_maximumbitrates_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UEAGGREGATE_MAXIMUMBITRATES_EXT_STRUCT         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEAggregate-MaximumBitrates-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UE_S1AP_ID_pair_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_s1ap_id_pair_ext(
  LIBLTE_S1AP_MESSAGE_UE_S1AP_ID_PAIR_EXT_STRUCT                     *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UE-S1AP-ID-pair-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_s1ap_id_pair_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UE_S1AP_ID_PAIR_EXT_STRUCT                     *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UE-S1AP-ID-pair-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UE_associatedLogicalS1_ConnectionItemExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionitemext(
  LIBLTE_S1AP_MESSAGE_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEMEXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UE-associatedLogicalS1-ConnectionItemExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_associatedlogicals1_connectionitemext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEMEXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UE-associatedLogicalS1-ConnectionItemExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UESecurityCapabilities_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uesecuritycapabilities_ext(
  LIBLTE_S1AP_MESSAGE_UESECURITYCAPABILITIES_EXT_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UESecurityCapabilities-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uesecuritycapabilities_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UESECURITYCAPABILITIES_EXT_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UESecurityCapabilities-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UserLocationInformation_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_userlocationinformation_ext(
  LIBLTE_S1AP_MESSAGE_USERLOCATIONINFORMATION_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UserLocationInformation-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_userlocationinformation_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_USERLOCATIONINFORMATION_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UserLocationInformation-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ENBX2ExtTLA_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbx2exttla_ext(
  LIBLTE_S1AP_MESSAGE_ENBX2EXTTLA_EXT_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBX2ExtTLA-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbx2exttla_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ENBX2EXTTLA_EXT_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBX2ExtTLA-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message SourceeNB_ToTargeteNB_TransparentContainer_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_sourceenb_totargetenb_transparentcontainer_ext(
  LIBLTE_S1AP_MESSAGE_SOURCEENB_TOTARGETENB_TRANSPARENTCONTAINER_EXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SourceeNB-ToTargeteNB-TransparentContainer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->MobilityInformation_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MobilityInformation
    if(msg->MobilityInformation_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mobilityinformation(&msg->MobilityInformation, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MOBILITYINFORMATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_sourceenb_totargetenb_transparentcontainer_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_SOURCEENB_TOTARGETENB_TRANSPARENTCONTAINER_EXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->MobilityInformation_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SourceeNB-ToTargeteNB-TransparentContainer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MOBILITYINFORMATION == ie_id) {
        if(liblte_s1ap_unpack_mobilityinformation(ptr, &msg->MobilityInformation) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MobilityInformation_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABInformationList STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabinformationlist(
  LIBLTE_S1AP_MESSAGE_E_RABINFORMATIONLIST_STRUCT                    *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABInformationListIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABInformationListItem
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabinformationlistitem(&msg->E_RABInformationListItem, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABINFORMATIONLISTITEM,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabinformationlist(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABINFORMATIONLIST_STRUCT                    *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABInformationListIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABINFORMATIONLISTITEM == ie_id) {
        if(liblte_s1ap_unpack_e_rabinformationlistitem(ptr, &msg->E_RABInformationListItem) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message LastVisitedEUTRANCellInformation_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_lastvisitedeutrancellinformation_ext(
  LIBLTE_S1AP_MESSAGE_LASTVISITEDEUTRANCELLINFORMATION_EXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LastVisitedEUTRANCellInformation-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 2;
    if(!msg->Time_UE_StayedInCell_EnhancedGranularity_present)
      n_ie--;
    if(!msg->HO_Cause_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Time_UE_StayedInCell_EnhancedGranularity
    if(msg->Time_UE_StayedInCell_EnhancedGranularity_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_time_ue_stayedincell_enhancedgranularity(&msg->Time_UE_StayedInCell_EnhancedGranularity, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TIME_UE_STAYEDINCELL_ENHANCEDGRANULARITY,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - HO_Cause
    if(msg->HO_Cause_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cause(&msg->HO_Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_HO_CAUSE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_lastvisitedeutrancellinformation_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_LASTVISITEDEUTRANCELLINFORMATION_EXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->Time_UE_StayedInCell_EnhancedGranularity_present = false;
    msg->HO_Cause_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LastVisitedEUTRANCellInformation-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_TIME_UE_STAYEDINCELL_ENHANCEDGRANULARITY == ie_id) {
        if(liblte_s1ap_unpack_time_ue_stayedincell_enhancedgranularity(ptr, &msg->Time_UE_StayedInCell_EnhancedGranularity) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Time_UE_StayedInCell_EnhancedGranularity_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_HO_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->HO_Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->HO_Cause_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message SONInformationReply_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_soninformationreply_ext(
  LIBLTE_S1AP_MESSAGE_SONINFORMATIONREPLY_EXT_STRUCT                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SONInformationReply-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->Time_Synchronization_Info_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Time_Synchronization_Info
    if(msg->Time_Synchronization_Info_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_timesynchronizationinfo(&msg->Time_Synchronization_Info, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TIME_SYNCHRONIZATION_INFO,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_soninformationreply_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_SONINFORMATIONREPLY_EXT_STRUCT                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->Time_Synchronization_Info_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SONInformationReply-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_TIME_SYNCHRONIZATION_INFO == ie_id) {
        if(liblte_s1ap_unpack_timesynchronizationinfo(ptr, &msg->Time_Synchronization_Info) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Time_Synchronization_Info_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message Bearers_SubjectToStatusTransfer_ItemExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_itemext(
  LIBLTE_S1AP_MESSAGE_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEMEXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("Bearers-SubjectToStatusTransfer-ItemExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->ULCOUNTValueExtended_present)
      n_ie--;
    if(!msg->DLCOUNTValueExtended_present)
      n_ie--;
    if(!msg->ReceiveStatusOfULPDCPSDUsExtended_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - ULCOUNTValueExtended
    if(msg->ULCOUNTValueExtended_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_countvalueextended(&msg->ULCOUNTValueExtended, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_ULCOUNTVALUEEXTENDED,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - DLCOUNTValueExtended
    if(msg->DLCOUNTValueExtended_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_countvalueextended(&msg->DLCOUNTValueExtended, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_DLCOUNTVALUEEXTENDED,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - ReceiveStatusOfULPDCPSDUsExtended
    if(msg->ReceiveStatusOfULPDCPSDUsExtended_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_receivestatusofulpdcpsdusextended(&msg->ReceiveStatusOfULPDCPSDUsExtended, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_RECEIVESTATUSOFULPDCPSDUSEXTENDED,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_bearers_subjecttostatustransfer_itemext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEMEXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->ULCOUNTValueExtended_present = false;
    msg->DLCOUNTValueExtended_present = false;
    msg->ReceiveStatusOfULPDCPSDUsExtended_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("Bearers-SubjectToStatusTransfer-ItemExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_ULCOUNTVALUEEXTENDED == ie_id) {
        if(liblte_s1ap_unpack_countvalueextended(ptr, &msg->ULCOUNTValueExtended) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->ULCOUNTValueExtended_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_DLCOUNTVALUEEXTENDED == ie_id) {
        if(liblte_s1ap_unpack_countvalueextended(ptr, &msg->DLCOUNTValueExtended) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->DLCOUNTValueExtended_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_RECEIVESTATUSOFULPDCPSDUSEXTENDED == ie_id) {
        if(liblte_s1ap_unpack_receivestatusofulpdcpsdusextended(ptr, &msg->ReceiveStatusOfULPDCPSDUsExtended) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->ReceiveStatusOfULPDCPSDUsExtended_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABItem STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabitem(
  LIBLTE_S1AP_MESSAGE_E_RABITEM_STRUCT                               *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABItem
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabitem(&msg->E_RABItem, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABITEM,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABITEM_STRUCT                               *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABITEM == ie_id) {
        if(liblte_s1ap_unpack_e_rabitem(ptr, &msg->E_RABItem) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message MDT_Configuration_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mdt_configuration_ext(
  LIBLTE_S1AP_MESSAGE_MDT_CONFIGURATION_EXT_STRUCT                   *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MDT-Configuration-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->SignallingBasedMDTPLMNList_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - SignallingBasedMDTPLMNList
    if(msg->SignallingBasedMDTPLMNList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mdtplmnlist(&msg->SignallingBasedMDTPLMNList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SIGNALLINGBASEDMDTPLMNLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mdt_configuration_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_MDT_CONFIGURATION_EXT_STRUCT                   *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->SignallingBasedMDTPLMNList_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MDT-Configuration-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_SIGNALLINGBASEDMDTPLMNLIST == ie_id) {
        if(liblte_s1ap_unpack_mdtplmnlist(ptr, &msg->SignallingBasedMDTPLMNList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SignallingBasedMDTPLMNList_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message X2TNLConfigurationInfo_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_x2tnlconfigurationinfo_ext(
  LIBLTE_S1AP_MESSAGE_X2TNLCONFIGURATIONINFO_EXT_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("X2TNLConfigurationInfo-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->eNBX2ExtendedTransportLayerAddresses_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - eNBX2ExtendedTransportLayerAddresses
    if(msg->eNBX2ExtendedTransportLayerAddresses_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_enbx2exttlas(&msg->eNBX2ExtendedTransportLayerAddresses, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_ENBX2EXTENDEDTRANSPORTLAYERADDRESSES,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_x2tnlconfigurationinfo_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_X2TNLCONFIGURATIONINFO_EXT_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->eNBX2ExtendedTransportLayerAddresses_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("X2TNLConfigurationInfo-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_ENBX2EXTENDEDTRANSPORTLAYERADDRESSES == ie_id) {
        if(liblte_s1ap_unpack_enbx2exttlas(ptr, &msg->eNBX2ExtendedTransportLayerAddresses) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->eNBX2ExtendedTransportLayerAddresses_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message Bearers_SubjectToStatusTransfer_Item STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_bearers_subjecttostatustransfer_item(
  LIBLTE_S1AP_MESSAGE_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEM_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("Bearers-SubjectToStatusTransfer-ItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Bearers_SubjectToStatusTransfer_Item
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_bearers_subjecttostatustransfer_item(&msg->Bearers_SubjectToStatusTransfer_Item, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEM,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_bearers_subjecttostatustransfer_item(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEM_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("Bearers-SubjectToStatusTransfer-ItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_BEARERS_SUBJECTTOSTATUSTRANSFER_ITEM == ie_id) {
        if(liblte_s1ap_unpack_bearers_subjecttostatustransfer_item(ptr, &msg->Bearers_SubjectToStatusTransfer_Item) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ImmediateMDT_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_immediatemdt_ext(
  LIBLTE_S1AP_MESSAGE_IMMEDIATEMDT_EXT_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ImmediateMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->M3Configuration_present)
      n_ie--;
    if(!msg->M4Configuration_present)
      n_ie--;
    if(!msg->M5Configuration_present)
      n_ie--;
    if(!msg->MDT_Location_Info_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - M3Configuration
    if(msg->M3Configuration_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_m3configuration(&msg->M3Configuration, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_M3CONFIGURATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - M4Configuration
    if(msg->M4Configuration_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_m4configuration(&msg->M4Configuration, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_M4CONFIGURATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - M5Configuration
    if(msg->M5Configuration_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_m5configuration(&msg->M5Configuration, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_M5CONFIGURATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - MDT_Location_Info
    if(msg->MDT_Location_Info_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mdt_location_info(&msg->MDT_Location_Info, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MDT_LOCATION_INFO,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_immediatemdt_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_IMMEDIATEMDT_EXT_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->M3Configuration_present = false;
    msg->M4Configuration_present = false;
    msg->M5Configuration_present = false;
    msg->MDT_Location_Info_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ImmediateMDT-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_M3CONFIGURATION == ie_id) {
        if(liblte_s1ap_unpack_m3configuration(ptr, &msg->M3Configuration) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_M4CONFIGURATION == ie_id) {
        if(liblte_s1ap_unpack_m4configuration(ptr, &msg->M4Configuration) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_M5CONFIGURATION == ie_id) {
        if(liblte_s1ap_unpack_m5configuration(ptr, &msg->M5Configuration) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_MDT_LOCATION_INFO == ie_id) {
        if(liblte_s1ap_unpack_mdt_location_info(ptr, &msg->MDT_Location_Info) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MDT_Location_Info_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message SONConfigurationTransfer_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_sonconfigurationtransfer_ext(
  LIBLTE_S1AP_MESSAGE_SONCONFIGURATIONTRANSFER_EXT_STRUCT            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SONConfigurationTransfer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->x2TNLConfigurationInfo_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - x2TNLConfigurationInfo
    if(msg->x2TNLConfigurationInfo_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_x2tnlconfigurationinfo(&msg->x2TNLConfigurationInfo, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_X2TNLCONFIGURATIONINFO,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_sonconfigurationtransfer_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_SONCONFIGURATIONTRANSFER_EXT_STRUCT            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->x2TNLConfigurationInfo_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("SONConfigurationTransfer-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_X2TNLCONFIGURATIONINFO == ie_id) {
        if(liblte_s1ap_unpack_x2tnlconfigurationinfo(ptr, &msg->x2TNLConfigurationInfo) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TraceActivation_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_traceactivation_ext(
  LIBLTE_S1AP_MESSAGE_TRACEACTIVATION_EXT_STRUCT                     *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TraceActivation-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->MDTConfiguration_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MDTConfiguration
    if(msg->MDTConfiguration_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mdt_configuration(&msg->MDTConfiguration, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MDTCONFIGURATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_traceactivation_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TRACEACTIVATION_EXT_STRUCT                     *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->MDTConfiguration_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TraceActivation-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MDTCONFIGURATION == ie_id) {
        if(liblte_s1ap_unpack_mdt_configuration(ptr, &msg->MDTConfiguration) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MDTConfiguration_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverRequired STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequired(
  LIBLTE_S1AP_MESSAGE_HANDOVERREQUIRED_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverRequiredIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 14;
    if(!msg->Direct_Forwarding_Path_Availability_present)
      n_ie--;
    if(!msg->SRVCCHOIndication_present)
      n_ie--;
    if(!msg->Source_ToTarget_TransparentContainer_Secondary_present)
      n_ie--;
    if(!msg->MSClassmark2_present)
      n_ie--;
    if(!msg->MSClassmark3_present)
      n_ie--;
    if(!msg->CSG_Id_present)
      n_ie--;
    if(!msg->CellAccessMode_present)
      n_ie--;
    if(!msg->PS_ServiceNotAvailable_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - HandoverType
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_handovertype(&msg->HandoverType, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_HANDOVERTYPE,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TargetID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_targetid(&msg->TargetID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TARGETID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Direct_Forwarding_Path_Availability
    if(msg->Direct_Forwarding_Path_Availability_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_direct_forwarding_path_availability(&msg->Direct_Forwarding_Path_Availability, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_DIRECT_FORWARDING_PATH_AVAILABILITY,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SRVCCHOIndication
    if(msg->SRVCCHOIndication_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_srvcchoindication(&msg->SRVCCHOIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SRVCCHOINDICATION,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - Source_ToTarget_TransparentContainer
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_source_totarget_transparentcontainer(&msg->Source_ToTarget_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SOURCE_TOTARGET_TRANSPARENTCONTAINER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Source_ToTarget_TransparentContainer_Secondary
    if(msg->Source_ToTarget_TransparentContainer_Secondary_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_source_totarget_transparentcontainer(&msg->Source_ToTarget_TransparentContainer_Secondary, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SOURCE_TOTARGET_TRANSPARENTCONTAINER_SECONDARY,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - MSClassmark2
    if(msg->MSClassmark2_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_msclassmark2(&msg->MSClassmark2, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MSCLASSMARK2,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - MSClassmark3
    if(msg->MSClassmark3_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_msclassmark3(&msg->MSClassmark3, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MSCLASSMARK3,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSG_Id
    if(msg->CSG_Id_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSG_ID,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CellAccessMode
    if(msg->CellAccessMode_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CELLACCESSMODE,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - PS_ServiceNotAvailable
    if(msg->PS_ServiceNotAvailable_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ps_servicenotavailable(&msg->PS_ServiceNotAvailable, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_PS_SERVICENOTAVAILABLE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handoverrequired(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERREQUIRED_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->Direct_Forwarding_Path_Availability_present = false;
    msg->SRVCCHOIndication_present = false;
    msg->Source_ToTarget_TransparentContainer_Secondary_present = false;
    msg->MSClassmark2_present = false;
    msg->MSClassmark3_present = false;
    msg->CSG_Id_present = false;
    msg->CellAccessMode_present = false;
    msg->PS_ServiceNotAvailable_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverRequiredIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_HANDOVERTYPE == ie_id) {
        if(liblte_s1ap_unpack_handovertype(ptr, &msg->HandoverType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TARGETID == ie_id) {
        if(liblte_s1ap_unpack_targetid(ptr, &msg->TargetID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_DIRECT_FORWARDING_PATH_AVAILABILITY == ie_id) {
        if(liblte_s1ap_unpack_direct_forwarding_path_availability(ptr, &msg->Direct_Forwarding_Path_Availability) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Direct_Forwarding_Path_Availability_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SRVCCHOINDICATION == ie_id) {
        if(liblte_s1ap_unpack_srvcchoindication(ptr, &msg->SRVCCHOIndication) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SRVCCHOIndication_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SOURCE_TOTARGET_TRANSPARENTCONTAINER == ie_id) {
        if(liblte_s1ap_unpack_source_totarget_transparentcontainer(ptr, &msg->Source_ToTarget_TransparentContainer) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_SOURCE_TOTARGET_TRANSPARENTCONTAINER_SECONDARY == ie_id) {
        if(liblte_s1ap_unpack_source_totarget_transparentcontainer(ptr, &msg->Source_ToTarget_TransparentContainer_Secondary) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Source_ToTarget_TransparentContainer_Secondary_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_MSCLASSMARK2 == ie_id) {
        if(liblte_s1ap_unpack_msclassmark2(ptr, &msg->MSClassmark2) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_MSCLASSMARK3 == ie_id) {
        if(liblte_s1ap_unpack_msclassmark3(ptr, &msg->MSClassmark3) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CSG_ID == ie_id) {
        if(liblte_s1ap_unpack_csg_id(ptr, &msg->CSG_Id) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSG_Id_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CELLACCESSMODE == ie_id) {
        if(liblte_s1ap_unpack_cellaccessmode(ptr, &msg->CellAccessMode) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CellAccessMode_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_PS_SERVICENOTAVAILABLE == ie_id) {
        if(liblte_s1ap_unpack_ps_servicenotavailable(ptr, &msg->PS_ServiceNotAvailable) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->PS_ServiceNotAvailable_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABDataForwardingItem_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabdataforwardingitem_ext(
  LIBLTE_S1AP_MESSAGE_E_RABDATAFORWARDINGITEM_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABDataForwardingItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabdataforwardingitem_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABDATAFORWARDINGITEM_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABDataForwardingItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverPreparationFailure STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverpreparationfailure(
  LIBLTE_S1AP_MESSAGE_HANDOVERPREPARATIONFAILURE_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverPreparationFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handoverpreparationfailure(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERPREPARATIONFAILURE_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverPreparationFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSetupItemHOReq_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemhoreq_ext(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMHOREQ_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemHOReq-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->Data_Forwarding_Not_Possible_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Data_Forwarding_Not_Possible
    if(msg->Data_Forwarding_Not_Possible_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_data_forwarding_not_possible(&msg->Data_Forwarding_Not_Possible, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_DATA_FORWARDING_NOT_POSSIBLE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetupitemhoreq_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMHOREQ_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->Data_Forwarding_Not_Possible_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemHOReq-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_DATA_FORWARDING_NOT_POSSIBLE == ie_id) {
        if(liblte_s1ap_unpack_data_forwarding_not_possible(ptr, &msg->Data_Forwarding_Not_Possible) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Data_Forwarding_Not_Possible_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABAdmittedItem_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabadmitteditem_ext(
  LIBLTE_S1AP_MESSAGE_E_RABADMITTEDITEM_EXT_STRUCT                   *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABAdmittedItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabadmitteditem_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABADMITTEDITEM_EXT_STRUCT                   *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABAdmittedItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABFailedToSetupItemHOReqAckExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabfailedtosetupitemhoreqackext(
  LIBLTE_S1AP_MESSAGE_E_RABFAILEDTOSETUPITEMHOREQACKEXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABFailedToSetupItemHOReqAckExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabfailedtosetupitemhoreqackext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABFAILEDTOSETUPITEMHOREQACKEXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABFailedToSetupItemHOReqAckExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverFailure STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverfailure(
  LIBLTE_S1AP_MESSAGE_HANDOVERFAILURE_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handoverfailure(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERFAILURE_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverNotify STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovernotify(
  LIBLTE_S1AP_MESSAGE_HANDOVERNOTIFY_STRUCT                          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverNotifyIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 6;
    if(!msg->Tunnel_Information_for_BBF_present)
      n_ie--;
    if(!msg->LHN_ID_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - EUTRAN_CGI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_EUTRAN_CGI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TAI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TAI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Tunnel_Information_for_BBF
    if(msg->Tunnel_Information_for_BBF_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_tunnelinformation(&msg->Tunnel_Information_for_BBF, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TUNNEL_INFORMATION_FOR_BBF,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - LHN_ID
    if(msg->LHN_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_LHN_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handovernotify(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERNOTIFY_STRUCT                          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->Tunnel_Information_for_BBF_present = false;
    msg->LHN_ID_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverNotifyIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_EUTRAN_CGI == ie_id) {
        if(liblte_s1ap_unpack_eutran_cgi(ptr, &msg->EUTRAN_CGI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TAI == ie_id) {
        if(liblte_s1ap_unpack_tai(ptr, &msg->TAI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TUNNEL_INFORMATION_FOR_BBF == ie_id) {
        if(liblte_s1ap_unpack_tunnelinformation(ptr, &msg->Tunnel_Information_for_BBF) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Tunnel_Information_for_BBF_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_LHN_ID == ie_id) {
        if(liblte_s1ap_unpack_lhn_id(ptr, &msg->LHN_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->LHN_ID_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSwitchedDLItem_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitcheddlitem_ext(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESWITCHEDDLITEM_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSwitchedDLItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobeswitcheddlitem_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESWITCHEDDLITEM_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSwitchedDLItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSwitchedULItem_Ext STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitchedulitem_ext(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESWITCHEDULITEM_EXT_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSwitchedULItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobeswitchedulitem_ext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESWITCHEDULITEM_EXT_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSwitchedULItem-ExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message PathSwitchRequestFailure STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestfailure(
  LIBLTE_S1AP_MESSAGE_PATHSWITCHREQUESTFAILURE_STRUCT                *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PathSwitchRequestFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pathswitchrequestfailure(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_PATHSWITCHREQUESTFAILURE_STRUCT                *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PathSwitchRequestFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverCancel STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancel(
  LIBLTE_S1AP_MESSAGE_HANDOVERCANCEL_STRUCT                          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverCancelIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handovercancel(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERCANCEL_STRUCT                          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverCancelIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverCancelAcknowledge STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercancelacknowledge(
  LIBLTE_S1AP_MESSAGE_HANDOVERCANCELACKNOWLEDGE_STRUCT               *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverCancelAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handovercancelacknowledge(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERCANCELACKNOWLEDGE_STRUCT               *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverCancelAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSetupItemBearerSUReqExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitembearersureqext(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMBEARERSUREQEXT_STRUCT        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemBearerSUReqExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 2;
    if(!msg->Correlation_ID_present)
      n_ie--;
    if(!msg->SIPTO_Correlation_ID_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Correlation_ID
    if(msg->Correlation_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_correlation_id(&msg->Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CORRELATION_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SIPTO_Correlation_ID
    if(msg->SIPTO_Correlation_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_correlation_id(&msg->SIPTO_Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SIPTO_CORRELATION_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetupitembearersureqext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMBEARERSUREQEXT_STRUCT        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->Correlation_ID_present = false;
    msg->SIPTO_Correlation_ID_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemBearerSUReqExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_CORRELATION_ID == ie_id) {
        if(liblte_s1ap_unpack_correlation_id(ptr, &msg->Correlation_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Correlation_ID_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SIPTO_CORRELATION_ID == ie_id) {
        if(liblte_s1ap_unpack_correlation_id(ptr, &msg->SIPTO_Correlation_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SIPTO_Correlation_ID_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABSetupItemBearerSUResExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitembearersuresext(
  LIBLTE_S1AP_MESSAGE_E_RABSETUPITEMBEARERSURESEXT_STRUCT            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupItemBearerSUResExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetupitembearersuresext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABSETUPITEMBEARERSURESEXT_STRUCT            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupItemBearerSUResExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeModifyItemBearerModReqExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifyitembearermodreqext(
  LIBLTE_S1AP_MESSAGE_E_RABTOBEMODIFYITEMBEARERMODREQEXT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeModifyItemBearerModReqExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->TransportInformation_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - TransportInformation
    if(msg->TransportInformation_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_transportinformation(&msg->TransportInformation, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TRANSPORTINFORMATION,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobemodifyitembearermodreqext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBEMODIFYITEMBEARERMODREQEXT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->TransportInformation_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeModifyItemBearerModReqExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_TRANSPORTINFORMATION == ie_id) {
        if(liblte_s1ap_unpack_transportinformation(ptr, &msg->TransportInformation) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->TransportInformation_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABModifyItemBearerModResExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyitembearermodresext(
  LIBLTE_S1AP_MESSAGE_E_RABMODIFYITEMBEARERMODRESEXT_STRUCT          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABModifyItemBearerModResExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabmodifyitembearermodresext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABMODIFYITEMBEARERMODRESEXT_STRUCT          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABModifyItemBearerModResExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABReleaseCommand STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleasecommand(
  LIBLTE_S1AP_MESSAGE_E_RABRELEASECOMMAND_STRUCT                     *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseCommandIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 5;
    if(!msg->uEaggregateMaximumBitrate_present)
      n_ie--;
    if(!msg->NAS_PDU_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - uEaggregateMaximumBitrate
    if(msg->uEaggregateMaximumBitrate_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABToBeReleasedList
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rablist(&msg->E_RABToBeReleasedList, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBERELEASEDLIST,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - NAS_PDU
    if(msg->NAS_PDU_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_NAS_PDU,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabreleasecommand(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABRELEASECOMMAND_STRUCT                     *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->uEaggregateMaximumBitrate_present = false;
    msg->NAS_PDU_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseCommandIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE == ie_id) {
        if(liblte_s1ap_unpack_ueaggregatemaximumbitrate(ptr, &msg->uEaggregateMaximumBitrate) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->uEaggregateMaximumBitrate_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_E_RABTOBERELEASEDLIST == ie_id) {
        if(liblte_s1ap_unpack_e_rablist(ptr, &msg->E_RABToBeReleasedList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_NAS_PDU == ie_id) {
        if(liblte_s1ap_unpack_nas_pdu(ptr, &msg->NAS_PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->NAS_PDU_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABReleaseItemBearerRelCompExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseitembearerrelcompext(
  LIBLTE_S1AP_MESSAGE_E_RABRELEASEITEMBEARERRELCOMPEXT_STRUCT        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseItemBearerRelCompExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabreleaseitembearerrelcompext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABRELEASEITEMBEARERRELCOMPEXT_STRUCT        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseItemBearerRelCompExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABReleaseIndication STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseindication(
  LIBLTE_S1AP_MESSAGE_E_RABRELEASEINDICATION_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->UserLocationInformation_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABReleasedList
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rablist(&msg->E_RABReleasedList, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABRELEASEDLIST,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - UserLocationInformation
    if(msg->UserLocationInformation_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_userlocationinformation(&msg->UserLocationInformation, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_USERLOCATIONINFORMATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabreleaseindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABRELEASEINDICATION_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->UserLocationInformation_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABRELEASEDLIST == ie_id) {
        if(liblte_s1ap_unpack_e_rablist(ptr, &msg->E_RABReleasedList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_USERLOCATIONINFORMATION == ie_id) {
        if(liblte_s1ap_unpack_userlocationinformation(ptr, &msg->UserLocationInformation) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->UserLocationInformation_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSetupItemCtxtSUReqExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemctxtsureqext(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMCTXTSUREQEXT_STRUCT          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemCtxtSUReqExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 2;
    if(!msg->Correlation_ID_present)
      n_ie--;
    if(!msg->SIPTO_Correlation_ID_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Correlation_ID
    if(msg->Correlation_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_correlation_id(&msg->Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CORRELATION_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SIPTO_Correlation_ID
    if(msg->SIPTO_Correlation_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_correlation_id(&msg->SIPTO_Correlation_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SIPTO_CORRELATION_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetupitemctxtsureqext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMCTXTSUREQEXT_STRUCT          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->Correlation_ID_present = false;
    msg->SIPTO_Correlation_ID_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemCtxtSUReqExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_CORRELATION_ID == ie_id) {
        if(liblte_s1ap_unpack_correlation_id(ptr, &msg->Correlation_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Correlation_ID_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SIPTO_CORRELATION_ID == ie_id) {
        if(liblte_s1ap_unpack_correlation_id(ptr, &msg->SIPTO_Correlation_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SIPTO_Correlation_ID_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABSetupItemCtxtSUResExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitemctxtsuresext(
  LIBLTE_S1AP_MESSAGE_E_RABSETUPITEMCTXTSURESEXT_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupItemCtxtSUResExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetupitemctxtsuresext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABSETUPITEMCTXTSURESEXT_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupItemCtxtSUResExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message InitialContextSetupFailure STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupfailure(
  LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPFAILURE_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("InitialContextSetupFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_initialcontextsetupfailure(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPFAILURE_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("InitialContextSetupFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TAIItemExt STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_taiitemext(
  LIBLTE_S1AP_MESSAGE_TAIITEMEXT_STRUCT                              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAIItemExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_taiitemext(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TAIITEMEXT_STRUCT                              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAIItemExtIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UEContextReleaseRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleaserequest(
  LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextReleaseRequest-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->GWContextReleaseIndication_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - GWContextReleaseIndication
    if(msg->GWContextReleaseIndication_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_gwcontextreleaseindication(&msg->GWContextReleaseIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_GWCONTEXTRELEASEINDICATION,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uecontextreleaserequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->GWContextReleaseIndication_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextReleaseRequest-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_GWCONTEXTRELEASEINDICATION == ie_id) {
        if(liblte_s1ap_unpack_gwcontextreleaseindication(ptr, &msg->GWContextReleaseIndication) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->GWContextReleaseIndication_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UEContextReleaseCommand STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecommand(
  LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMAND_STRUCT                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextReleaseCommand-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 2;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - UE_S1AP_IDs
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_ue_s1ap_ids(&msg->UE_S1AP_IDs, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UE_S1AP_IDS,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uecontextreleasecommand(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMAND_STRUCT                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextReleaseCommand-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_UE_S1AP_IDS == ie_id) {
        if(liblte_s1ap_unpack_ue_s1ap_ids(ptr, &msg->UE_S1AP_IDs) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UEContextReleaseComplete STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextreleasecomplete(
  LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT                *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextReleaseComplete-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    if(!msg->UserLocationInformation_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - UserLocationInformation
    if(msg->UserLocationInformation_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_userlocationinformation(&msg->UserLocationInformation, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_USERLOCATIONINFORMATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uecontextreleasecomplete(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT                *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;
    msg->UserLocationInformation_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextReleaseComplete-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_USERLOCATIONINFORMATION == ie_id) {
        if(liblte_s1ap_unpack_userlocationinformation(ptr, &msg->UserLocationInformation) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->UserLocationInformation_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UEContextModificationRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationrequest(
  LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextModificationRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 10;
    if(!msg->SecurityKey_present)
      n_ie--;
    if(!msg->SubscriberProfileIDforRFP_present)
      n_ie--;
    if(!msg->uEaggregateMaximumBitrate_present)
      n_ie--;
    if(!msg->CSFallbackIndicator_present)
      n_ie--;
    if(!msg->UESecurityCapabilities_present)
      n_ie--;
    if(!msg->CSGMembershipStatus_present)
      n_ie--;
    if(!msg->RegisteredLAI_present)
      n_ie--;
    if(!msg->AdditionalCSFallbackIndicator_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - SecurityKey
    if(msg->SecurityKey_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_securitykey(&msg->SecurityKey, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SECURITYKEY,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SubscriberProfileIDforRFP
    if(msg->SubscriberProfileIDforRFP_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_subscriberprofileidforrfp(&msg->SubscriberProfileIDforRFP, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SUBSCRIBERPROFILEIDFORRFP,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - uEaggregateMaximumBitrate
    if(msg->uEaggregateMaximumBitrate_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSFallbackIndicator
    if(msg->CSFallbackIndicator_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csfallbackindicator(&msg->CSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSFALLBACKINDICATOR,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - UESecurityCapabilities
    if(msg->UESecurityCapabilities_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UESECURITYCAPABILITIES,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSGMembershipStatus
    if(msg->CSGMembershipStatus_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - RegisteredLAI
    if(msg->RegisteredLAI_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_lai(&msg->RegisteredLAI, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_REGISTEREDLAI,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - AdditionalCSFallbackIndicator
    if(msg->AdditionalCSFallbackIndicator_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_additionalcsfallbackindicator(&msg->AdditionalCSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_ADDITIONALCSFALLBACKINDICATOR,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uecontextmodificationrequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->SecurityKey_present = false;
    msg->SubscriberProfileIDforRFP_present = false;
    msg->uEaggregateMaximumBitrate_present = false;
    msg->CSFallbackIndicator_present = false;
    msg->UESecurityCapabilities_present = false;
    msg->CSGMembershipStatus_present = false;
    msg->RegisteredLAI_present = false;
    msg->AdditionalCSFallbackIndicator_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextModificationRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_SECURITYKEY == ie_id) {
        if(liblte_s1ap_unpack_securitykey(ptr, &msg->SecurityKey) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SecurityKey_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SUBSCRIBERPROFILEIDFORRFP == ie_id) {
        if(liblte_s1ap_unpack_subscriberprofileidforrfp(ptr, &msg->SubscriberProfileIDforRFP) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SubscriberProfileIDforRFP_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE == ie_id) {
        if(liblte_s1ap_unpack_ueaggregatemaximumbitrate(ptr, &msg->uEaggregateMaximumBitrate) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->uEaggregateMaximumBitrate_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CSFALLBACKINDICATOR == ie_id) {
        if(liblte_s1ap_unpack_csfallbackindicator(ptr, &msg->CSFallbackIndicator) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSFallbackIndicator_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_UESECURITYCAPABILITIES == ie_id) {
        if(liblte_s1ap_unpack_uesecuritycapabilities(ptr, &msg->UESecurityCapabilities) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->UESecurityCapabilities_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS == ie_id) {
        if(liblte_s1ap_unpack_csgmembershipstatus(ptr, &msg->CSGMembershipStatus) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSGMembershipStatus_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_REGISTEREDLAI == ie_id) {
        if(liblte_s1ap_unpack_lai(ptr, &msg->RegisteredLAI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->RegisteredLAI_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_ADDITIONALCSFALLBACKINDICATOR == ie_id) {
        if(liblte_s1ap_unpack_additionalcsfallbackindicator(ptr, &msg->AdditionalCSFallbackIndicator) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UEContextModificationResponse STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationresponse(
  LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONRESPONSE_STRUCT           *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextModificationResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uecontextmodificationresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONRESPONSE_STRUCT           *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextModificationResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UEContextModificationFailure STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecontextmodificationfailure(
  LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONFAILURE_STRUCT            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextModificationFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uecontextmodificationfailure(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONFAILURE_STRUCT            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UEContextModificationFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UERadioCapabilityMatchRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchrequest(
  LIBLTE_S1AP_MESSAGE_UERADIOCAPABILITYMATCHREQUEST_STRUCT           *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UERadioCapabilityMatchRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->UERadioCapability_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - UERadioCapability
    if(msg->UERadioCapability_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ueradiocapability(&msg->UERadioCapability, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UERADIOCAPABILITY,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ueradiocapabilitymatchrequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UERADIOCAPABILITYMATCHREQUEST_STRUCT           *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->UERadioCapability_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UERadioCapabilityMatchRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UERADIOCAPABILITY == ie_id) {
        if(liblte_s1ap_unpack_ueradiocapability(ptr, &msg->UERadioCapability) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->UERadioCapability_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UERadioCapabilityMatchResponse STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ueradiocapabilitymatchresponse(
  LIBLTE_S1AP_MESSAGE_UERADIOCAPABILITYMATCHRESPONSE_STRUCT          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UERadioCapabilityMatchResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - VoiceSupportMatchIndicator
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_voicesupportmatchindicator(&msg->VoiceSupportMatchIndicator, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_VOICESUPPORTMATCHINDICATOR,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ueradiocapabilitymatchresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UERADIOCAPABILITYMATCHRESPONSE_STRUCT          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UERadioCapabilityMatchResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_VOICESUPPORTMATCHINDICATOR == ie_id) {
        if(liblte_s1ap_unpack_voicesupportmatchindicator(ptr, &msg->VoiceSupportMatchIndicator) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message DownlinkNASTransport STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknastransport(
  LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT                    *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DownlinkNASTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 5;
    if(!msg->HandoverRestrictionList_present)
      n_ie--;
    if(!msg->SubscriberProfileIDforRFP_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - NAS_PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_NAS_PDU,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - HandoverRestrictionList
    if(msg->HandoverRestrictionList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_handoverrestrictionlist(&msg->HandoverRestrictionList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_HANDOVERRESTRICTIONLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SubscriberProfileIDforRFP
    if(msg->SubscriberProfileIDforRFP_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_subscriberprofileidforrfp(&msg->SubscriberProfileIDforRFP, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SUBSCRIBERPROFILEIDFORRFP,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_downlinknastransport(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT                    *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->HandoverRestrictionList_present = false;
    msg->SubscriberProfileIDforRFP_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DownlinkNASTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_NAS_PDU == ie_id) {
        if(liblte_s1ap_unpack_nas_pdu(ptr, &msg->NAS_PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_HANDOVERRESTRICTIONLIST == ie_id) {
        if(liblte_s1ap_unpack_handoverrestrictionlist(ptr, &msg->HandoverRestrictionList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->HandoverRestrictionList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SUBSCRIBERPROFILEIDFORRFP == ie_id) {
        if(liblte_s1ap_unpack_subscriberprofileidforrfp(ptr, &msg->SubscriberProfileIDforRFP) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SubscriberProfileIDforRFP_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message InitialUEMessage STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialuemessage(
  LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("InitialUEMessage-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 15;
    if(!msg->S_TMSI_present)
      n_ie--;
    if(!msg->CSG_Id_present)
      n_ie--;
    if(!msg->GUMMEI_ID_present)
      n_ie--;
    if(!msg->CellAccessMode_present)
      n_ie--;
    if(!msg->GW_TransportLayerAddress_present)
      n_ie--;
    if(!msg->RelayNode_Indicator_present)
      n_ie--;
    if(!msg->GUMMEIType_present)
      n_ie--;
    if(!msg->Tunnel_Information_for_BBF_present)
      n_ie--;
    if(!msg->SIPTO_L_GW_TransportLayerAddress_present)
      n_ie--;
    if(!msg->LHN_ID_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - NAS_PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_NAS_PDU,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TAI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TAI,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - EUTRAN_CGI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_EUTRAN_CGI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - RRC_Establishment_Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_rrc_establishment_cause(&msg->RRC_Establishment_Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_RRC_ESTABLISHMENT_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - S_TMSI
    if(msg->S_TMSI_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_s_tmsi(&msg->S_TMSI, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_S_TMSI,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSG_Id
    if(msg->CSG_Id_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSG_ID,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - GUMMEI_ID
    if(msg->GUMMEI_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_gummei(&msg->GUMMEI_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_GUMMEI_ID,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CellAccessMode
    if(msg->CellAccessMode_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CELLACCESSMODE,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - GW_TransportLayerAddress
    if(msg->GW_TransportLayerAddress_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_transportlayeraddress(&msg->GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_GW_TRANSPORTLAYERADDRESS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - RelayNode_Indicator
    if(msg->RelayNode_Indicator_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_relaynode_indicator(&msg->RelayNode_Indicator, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_RELAYNODE_INDICATOR,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - GUMMEIType
    if(msg->GUMMEIType_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_gummeitype(&msg->GUMMEIType, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_GUMMEITYPE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - Tunnel_Information_for_BBF
    if(msg->Tunnel_Information_for_BBF_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_tunnelinformation(&msg->Tunnel_Information_for_BBF, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TUNNEL_INFORMATION_FOR_BBF,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SIPTO_L_GW_TransportLayerAddress
    if(msg->SIPTO_L_GW_TransportLayerAddress_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_transportlayeraddress(&msg->SIPTO_L_GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SIPTO_L_GW_TRANSPORTLAYERADDRESS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - LHN_ID
    if(msg->LHN_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_LHN_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_initialuemessage(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->S_TMSI_present = false;
    msg->CSG_Id_present = false;
    msg->GUMMEI_ID_present = false;
    msg->CellAccessMode_present = false;
    msg->GW_TransportLayerAddress_present = false;
    msg->RelayNode_Indicator_present = false;
    msg->GUMMEIType_present = false;
    msg->Tunnel_Information_for_BBF_present = false;
    msg->SIPTO_L_GW_TransportLayerAddress_present = false;
    msg->LHN_ID_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("InitialUEMessage-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_NAS_PDU == ie_id) {
        if(liblte_s1ap_unpack_nas_pdu(ptr, &msg->NAS_PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TAI == ie_id) {
        if(liblte_s1ap_unpack_tai(ptr, &msg->TAI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_EUTRAN_CGI == ie_id) {
        if(liblte_s1ap_unpack_eutran_cgi(ptr, &msg->EUTRAN_CGI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_RRC_ESTABLISHMENT_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_rrc_establishment_cause(ptr, &msg->RRC_Establishment_Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_S_TMSI == ie_id) {
        if(liblte_s1ap_unpack_s_tmsi(ptr, &msg->S_TMSI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->S_TMSI_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CSG_ID == ie_id) {
        if(liblte_s1ap_unpack_csg_id(ptr, &msg->CSG_Id) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSG_Id_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_GUMMEI_ID == ie_id) {
        if(liblte_s1ap_unpack_gummei(ptr, &msg->GUMMEI_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->GUMMEI_ID_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CELLACCESSMODE == ie_id) {
        if(liblte_s1ap_unpack_cellaccessmode(ptr, &msg->CellAccessMode) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CellAccessMode_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_GW_TRANSPORTLAYERADDRESS == ie_id) {
        if(liblte_s1ap_unpack_transportlayeraddress(ptr, &msg->GW_TransportLayerAddress) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->GW_TransportLayerAddress_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_RELAYNODE_INDICATOR == ie_id) {
        if(liblte_s1ap_unpack_relaynode_indicator(ptr, &msg->RelayNode_Indicator) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->RelayNode_Indicator_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_GUMMEITYPE == ie_id) {
        if(liblte_s1ap_unpack_gummeitype(ptr, &msg->GUMMEIType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->GUMMEIType_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_TUNNEL_INFORMATION_FOR_BBF == ie_id) {
        if(liblte_s1ap_unpack_tunnelinformation(ptr, &msg->Tunnel_Information_for_BBF) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Tunnel_Information_for_BBF_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SIPTO_L_GW_TRANSPORTLAYERADDRESS == ie_id) {
        if(liblte_s1ap_unpack_transportlayeraddress(ptr, &msg->SIPTO_L_GW_TransportLayerAddress) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SIPTO_L_GW_TransportLayerAddress_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_LHN_ID == ie_id) {
        if(liblte_s1ap_unpack_lhn_id(ptr, &msg->LHN_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->LHN_ID_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UplinkNASTransport STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknastransport(
  LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT                      *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UplinkNASTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 8;
    if(!msg->GW_TransportLayerAddress_present)
      n_ie--;
    if(!msg->SIPTO_L_GW_TransportLayerAddress_present)
      n_ie--;
    if(!msg->LHN_ID_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - NAS_PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_NAS_PDU,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - EUTRAN_CGI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_EUTRAN_CGI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TAI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TAI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - GW_TransportLayerAddress
    if(msg->GW_TransportLayerAddress_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_transportlayeraddress(&msg->GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_GW_TRANSPORTLAYERADDRESS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SIPTO_L_GW_TransportLayerAddress
    if(msg->SIPTO_L_GW_TransportLayerAddress_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_transportlayeraddress(&msg->SIPTO_L_GW_TransportLayerAddress, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SIPTO_L_GW_TRANSPORTLAYERADDRESS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - LHN_ID
    if(msg->LHN_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_LHN_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uplinknastransport(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT                      *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->GW_TransportLayerAddress_present = false;
    msg->SIPTO_L_GW_TransportLayerAddress_present = false;
    msg->LHN_ID_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UplinkNASTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_NAS_PDU == ie_id) {
        if(liblte_s1ap_unpack_nas_pdu(ptr, &msg->NAS_PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_EUTRAN_CGI == ie_id) {
        if(liblte_s1ap_unpack_eutran_cgi(ptr, &msg->EUTRAN_CGI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TAI == ie_id) {
        if(liblte_s1ap_unpack_tai(ptr, &msg->TAI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_GW_TRANSPORTLAYERADDRESS == ie_id) {
        if(liblte_s1ap_unpack_transportlayeraddress(ptr, &msg->GW_TransportLayerAddress) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->GW_TransportLayerAddress_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SIPTO_L_GW_TRANSPORTLAYERADDRESS == ie_id) {
        if(liblte_s1ap_unpack_transportlayeraddress(ptr, &msg->SIPTO_L_GW_TransportLayerAddress) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SIPTO_L_GW_TransportLayerAddress_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_LHN_ID == ie_id) {
        if(liblte_s1ap_unpack_lhn_id(ptr, &msg->LHN_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->LHN_ID_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message NASNonDeliveryIndication STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_nasnondeliveryindication(
  LIBLTE_S1AP_MESSAGE_NASNONDELIVERYINDICATION_STRUCT                *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("NASNonDeliveryIndication-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - NAS_PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_nas_pdu(&msg->NAS_PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_NAS_PDU,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_nasnondeliveryindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_NASNONDELIVERYINDICATION_STRUCT                *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("NASNonDeliveryIndication-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_NAS_PDU == ie_id) {
        if(liblte_s1ap_unpack_nas_pdu(ptr, &msg->NAS_PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UE_associatedLogicalS1_ConnectionItem STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(
  LIBLTE_S1AP_MESSAGE_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UE-associatedLogicalS1-ConnectionItemRes error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - UE_associatedLogicalS1_ConnectionItem
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&msg->UE_associatedLogicalS1_ConnectionItem, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_associatedlogicals1_connectionitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UE-associatedLogicalS1-ConnectionItemRes error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM == ie_id) {
        if(liblte_s1ap_unpack_ue_associatedlogicals1_connectionitem(ptr, &msg->UE_associatedLogicalS1_ConnectionItem) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UE_associatedLogicalS1_ConnectionItemRes STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_ue_associatedlogicals1_connectionitemres(
  LIBLTE_S1AP_MESSAGE_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEMRES_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UE-associatedLogicalS1-ConnectionItemResAck error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - UE_associatedLogicalS1_ConnectionItem
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_ue_associatedlogicals1_connectionitem(&msg->UE_associatedLogicalS1_ConnectionItem, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_ue_associatedlogicals1_connectionitemres(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEMRES_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UE-associatedLogicalS1-ConnectionItemResAck error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONITEM == ie_id) {
        if(liblte_s1ap_unpack_ue_associatedlogicals1_connectionitem(ptr, &msg->UE_associatedLogicalS1_ConnectionItem) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ErrorIndication STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_errorindication(
  LIBLTE_S1AP_MESSAGE_ERRORINDICATION_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ErrorIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->MME_UE_S1AP_ID_present)
      n_ie--;
    if(!msg->eNB_UE_S1AP_ID_present)
      n_ie--;
    if(!msg->Cause_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    if(msg->MME_UE_S1AP_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - eNB_UE_S1AP_ID
    if(msg->eNB_UE_S1AP_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - Cause
    if(msg->Cause_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CAUSE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_errorindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ERRORINDICATION_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->MME_UE_S1AP_ID_present = false;
    msg->eNB_UE_S1AP_ID_present = false;
    msg->Cause_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ErrorIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MME_UE_S1AP_ID_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->eNB_UE_S1AP_ID_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Cause_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message S1SetupRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setuprequest(
  LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT                          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("S1SetupRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 5;
    if(!msg->eNBname_present)
      n_ie--;
    if(!msg->CSG_IdList_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Global_ENB_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_global_enb_id(&msg->Global_ENB_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_GLOBAL_ENB_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNBname
    if(msg->eNBname_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_enbname(&msg->eNBname, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_ENBNAME,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SupportedTAs
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_supportedtas(&msg->SupportedTAs, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SUPPORTEDTAS,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - DefaultPagingDRX
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_pagingdrx(&msg->DefaultPagingDRX, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_DEFAULTPAGINGDRX,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CSG_IdList
    if(msg->CSG_IdList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csg_idlist(&msg->CSG_IdList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSG_IDLIST,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_s1setuprequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT                          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->eNBname_present = false;
    msg->CSG_IdList_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("S1SetupRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_GLOBAL_ENB_ID == ie_id) {
        if(liblte_s1ap_unpack_global_enb_id(ptr, &msg->Global_ENB_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENBNAME == ie_id) {
        if(liblte_s1ap_unpack_enbname(ptr, &msg->eNBname) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->eNBname_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SUPPORTEDTAS == ie_id) {
        if(liblte_s1ap_unpack_supportedtas(ptr, &msg->SupportedTAs) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_DEFAULTPAGINGDRX == ie_id) {
        if(liblte_s1ap_unpack_pagingdrx(ptr, &msg->DefaultPagingDRX) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CSG_IDLIST == ie_id) {
        if(liblte_s1ap_unpack_csg_idlist(ptr, &msg->CSG_IdList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSG_IdList_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message S1SetupResponse STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupresponse(
  LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("S1SetupResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 5;
    if(!msg->MMEname_present)
      n_ie--;
    if(!msg->MMERelaySupportIndicator_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MMEname
    if(msg->MMEname_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mmename(&msg->MMEname, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MMENAME,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - ServedGUMMEIs
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_servedgummeis(&msg->ServedGUMMEIs, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SERVEDGUMMEIS,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - RelativeMMECapacity
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_relativemmecapacity(&msg->RelativeMMECapacity, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_RELATIVEMMECAPACITY,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - MMERelaySupportIndicator
    if(msg->MMERelaySupportIndicator_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mmerelaysupportindicator(&msg->MMERelaySupportIndicator, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MMERELAYSUPPORTINDICATOR,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_s1setupresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->MMEname_present = false;
    msg->MMERelaySupportIndicator_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("S1SetupResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MMENAME == ie_id) {
        if(liblte_s1ap_unpack_mmename(ptr, &msg->MMEname) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MMEname_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SERVEDGUMMEIS == ie_id) {
        if(liblte_s1ap_unpack_servedgummeis(ptr, &msg->ServedGUMMEIs) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_RELATIVEMMECAPACITY == ie_id) {
        if(liblte_s1ap_unpack_relativemmecapacity(ptr, &msg->RelativeMMECapacity) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_MMERELAYSUPPORTINDICATOR == ie_id) {
        if(liblte_s1ap_unpack_mmerelaysupportindicator(ptr, &msg->MMERelaySupportIndicator) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MMERelaySupportIndicator_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message S1SetupFailure STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1setupfailure(
  LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT                          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("S1SetupFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->TimeToWait_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TimeToWait
    if(msg->TimeToWait_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_timetowait(&msg->TimeToWait, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TIMETOWAIT,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_s1setupfailure(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT                          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->TimeToWait_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("S1SetupFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TIMETOWAIT == ie_id) {
        if(liblte_s1ap_unpack_timetowait(ptr, &msg->TimeToWait) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->TimeToWait_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ENBConfigurationUpdate STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdate(
  LIBLTE_S1AP_MESSAGE_ENBCONFIGURATIONUPDATE_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBConfigurationUpdateIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->eNBname_present)
      n_ie--;
    if(!msg->SupportedTAs_present)
      n_ie--;
    if(!msg->CSG_IdList_present)
      n_ie--;
    if(!msg->DefaultPagingDRX_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - eNBname
    if(msg->eNBname_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_enbname(&msg->eNBname, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_ENBNAME,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SupportedTAs
    if(msg->SupportedTAs_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_supportedtas(&msg->SupportedTAs, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SUPPORTEDTAS,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSG_IdList
    if(msg->CSG_IdList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csg_idlist(&msg->CSG_IdList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSG_IDLIST,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - DefaultPagingDRX
    if(msg->DefaultPagingDRX_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_pagingdrx(&msg->DefaultPagingDRX, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_DEFAULTPAGINGDRX,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbconfigurationupdate(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ENBCONFIGURATIONUPDATE_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->eNBname_present = false;
    msg->SupportedTAs_present = false;
    msg->CSG_IdList_present = false;
    msg->DefaultPagingDRX_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBConfigurationUpdateIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_ENBNAME == ie_id) {
        if(liblte_s1ap_unpack_enbname(ptr, &msg->eNBname) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->eNBname_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SUPPORTEDTAS == ie_id) {
        if(liblte_s1ap_unpack_supportedtas(ptr, &msg->SupportedTAs) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SupportedTAs_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CSG_IDLIST == ie_id) {
        if(liblte_s1ap_unpack_csg_idlist(ptr, &msg->CSG_IdList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSG_IdList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_DEFAULTPAGINGDRX == ie_id) {
        if(liblte_s1ap_unpack_pagingdrx(ptr, &msg->DefaultPagingDRX) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->DefaultPagingDRX_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ENBConfigurationUpdateAcknowledge STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdateacknowledge(
  LIBLTE_S1AP_MESSAGE_ENBCONFIGURATIONUPDATEACKNOWLEDGE_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBConfigurationUpdateAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbconfigurationupdateacknowledge(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ENBCONFIGURATIONUPDATEACKNOWLEDGE_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBConfigurationUpdateAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ENBConfigurationUpdateFailure STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationupdatefailure(
  LIBLTE_S1AP_MESSAGE_ENBCONFIGURATIONUPDATEFAILURE_STRUCT           *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBConfigurationUpdateFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->TimeToWait_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TimeToWait
    if(msg->TimeToWait_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_timetowait(&msg->TimeToWait, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TIMETOWAIT,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbconfigurationupdatefailure(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ENBCONFIGURATIONUPDATEFAILURE_STRUCT           *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->TimeToWait_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBConfigurationUpdateFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TIMETOWAIT == ie_id) {
        if(liblte_s1ap_unpack_timetowait(ptr, &msg->TimeToWait) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->TimeToWait_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message MMEConfigurationUpdate STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdate(
  LIBLTE_S1AP_MESSAGE_MMECONFIGURATIONUPDATE_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEConfigurationUpdateIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->MMEname_present)
      n_ie--;
    if(!msg->ServedGUMMEIs_present)
      n_ie--;
    if(!msg->RelativeMMECapacity_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MMEname
    if(msg->MMEname_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mmename(&msg->MMEname, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MMENAME,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - ServedGUMMEIs
    if(msg->ServedGUMMEIs_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_servedgummeis(&msg->ServedGUMMEIs, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SERVEDGUMMEIS,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - RelativeMMECapacity
    if(msg->RelativeMMECapacity_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_relativemmecapacity(&msg->RelativeMMECapacity, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_RELATIVEMMECAPACITY,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mmeconfigurationupdate(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_MMECONFIGURATIONUPDATE_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->MMEname_present = false;
    msg->ServedGUMMEIs_present = false;
    msg->RelativeMMECapacity_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEConfigurationUpdateIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MMENAME == ie_id) {
        if(liblte_s1ap_unpack_mmename(ptr, &msg->MMEname) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MMEname_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SERVEDGUMMEIS == ie_id) {
        if(liblte_s1ap_unpack_servedgummeis(ptr, &msg->ServedGUMMEIs) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->ServedGUMMEIs_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_RELATIVEMMECAPACITY == ie_id) {
        if(liblte_s1ap_unpack_relativemmecapacity(ptr, &msg->RelativeMMECapacity) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->RelativeMMECapacity_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message MMEConfigurationUpdateAcknowledge STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdateacknowledge(
  LIBLTE_S1AP_MESSAGE_MMECONFIGURATIONUPDATEACKNOWLEDGE_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEConfigurationUpdateAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mmeconfigurationupdateacknowledge(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_MMECONFIGURATIONUPDATEACKNOWLEDGE_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEConfigurationUpdateAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message MMEConfigurationUpdateFailure STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationupdatefailure(
  LIBLTE_S1AP_MESSAGE_MMECONFIGURATIONUPDATEFAILURE_STRUCT           *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEConfigurationUpdateFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->TimeToWait_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TimeToWait
    if(msg->TimeToWait_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_timetowait(&msg->TimeToWait, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TIMETOWAIT,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mmeconfigurationupdatefailure(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_MMECONFIGURATIONUPDATEFAILURE_STRUCT           *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->TimeToWait_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEConfigurationUpdateFailureIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TIMETOWAIT == ie_id) {
        if(liblte_s1ap_unpack_timetowait(ptr, &msg->TimeToWait) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->TimeToWait_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UplinkS1cdma2000tunneling STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinks1cdma2000tunneling(
  LIBLTE_S1AP_MESSAGE_UPLINKS1CDMA2000TUNNELING_STRUCT               *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UplinkS1cdma2000tunnelingIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 9;
    if(!msg->cdma2000HORequiredIndication_present)
      n_ie--;
    if(!msg->cdma2000OneXSRVCCInfo_present)
      n_ie--;
    if(!msg->cdma2000OneXRAND_present)
      n_ie--;
    if(!msg->EUTRANRoundTripDelayEstimationInfo_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - cdma2000RATType
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cdma2000rattype(&msg->cdma2000RATType, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CDMA2000RATTYPE,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - cdma2000SectorID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cdma2000sectorid(&msg->cdma2000SectorID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CDMA2000SECTORID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - cdma2000HORequiredIndication
    if(msg->cdma2000HORequiredIndication_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cdma2000horequiredindication(&msg->cdma2000HORequiredIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CDMA2000HOREQUIREDINDICATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - cdma2000OneXSRVCCInfo
    if(msg->cdma2000OneXSRVCCInfo_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cdma2000onexsrvccinfo(&msg->cdma2000OneXSRVCCInfo, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CDMA2000ONEXSRVCCINFO,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - cdma2000OneXRAND
    if(msg->cdma2000OneXRAND_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cdma2000onexrand(&msg->cdma2000OneXRAND, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CDMA2000ONEXRAND,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - cdma2000PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cdma2000pdu(&msg->cdma2000PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CDMA2000PDU,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - EUTRANRoundTripDelayEstimationInfo
    if(msg->EUTRANRoundTripDelayEstimationInfo_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_eutranroundtripdelayestimationinfo(&msg->EUTRANRoundTripDelayEstimationInfo, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_EUTRANROUNDTRIPDELAYESTIMATIONINFO,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uplinks1cdma2000tunneling(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UPLINKS1CDMA2000TUNNELING_STRUCT               *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->cdma2000HORequiredIndication_present = false;
    msg->cdma2000OneXSRVCCInfo_present = false;
    msg->cdma2000OneXRAND_present = false;
    msg->EUTRANRoundTripDelayEstimationInfo_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UplinkS1cdma2000tunnelingIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CDMA2000RATTYPE == ie_id) {
        if(liblte_s1ap_unpack_cdma2000rattype(ptr, &msg->cdma2000RATType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CDMA2000SECTORID == ie_id) {
        if(liblte_s1ap_unpack_cdma2000sectorid(ptr, &msg->cdma2000SectorID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CDMA2000HOREQUIREDINDICATION == ie_id) {
        if(liblte_s1ap_unpack_cdma2000horequiredindication(ptr, &msg->cdma2000HORequiredIndication) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->cdma2000HORequiredIndication_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CDMA2000ONEXSRVCCINFO == ie_id) {
        if(liblte_s1ap_unpack_cdma2000onexsrvccinfo(ptr, &msg->cdma2000OneXSRVCCInfo) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->cdma2000OneXSRVCCInfo_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CDMA2000ONEXRAND == ie_id) {
        if(liblte_s1ap_unpack_cdma2000onexrand(ptr, &msg->cdma2000OneXRAND) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->cdma2000OneXRAND_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CDMA2000PDU == ie_id) {
        if(liblte_s1ap_unpack_cdma2000pdu(ptr, &msg->cdma2000PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_EUTRANROUNDTRIPDELAYESTIMATIONINFO == ie_id) {
        if(liblte_s1ap_unpack_eutranroundtripdelayestimationinfo(ptr, &msg->EUTRANRoundTripDelayEstimationInfo) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->EUTRANRoundTripDelayEstimationInfo_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UECapabilityInfoIndication STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uecapabilityinfoindication(
  LIBLTE_S1AP_MESSAGE_UECAPABILITYINFOINDICATION_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UECapabilityInfoIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - UERadioCapability
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_ueradiocapability(&msg->UERadioCapability, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UERADIOCAPABILITY,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uecapabilityinfoindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UECAPABILITYINFOINDICATION_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UECapabilityInfoIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UERADIOCAPABILITY == ie_id) {
        if(liblte_s1ap_unpack_ueradiocapability(ptr, &msg->UERadioCapability) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ENBStatusTransfer STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbstatustransfer(
  LIBLTE_S1AP_MESSAGE_ENBSTATUSTRANSFER_STRUCT                       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBStatusTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_StatusTransfer_TransparentContainer
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_statustransfer_transparentcontainer(&msg->eNB_StatusTransfer_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_STATUSTRANSFER_TRANSPARENTCONTAINER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbstatustransfer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ENBSTATUSTRANSFER_STRUCT                       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBStatusTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_STATUSTRANSFER_TRANSPARENTCONTAINER == ie_id) {
        if(liblte_s1ap_unpack_enb_statustransfer_transparentcontainer(ptr, &msg->eNB_StatusTransfer_TransparentContainer) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message MMEStatusTransfer STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmestatustransfer(
  LIBLTE_S1AP_MESSAGE_MMESTATUSTRANSFER_STRUCT                       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEStatusTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_StatusTransfer_TransparentContainer
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_statustransfer_transparentcontainer(&msg->eNB_StatusTransfer_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_STATUSTRANSFER_TRANSPARENTCONTAINER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mmestatustransfer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_MMESTATUSTRANSFER_STRUCT                       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEStatusTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_STATUSTRANSFER_TRANSPARENTCONTAINER == ie_id) {
        if(liblte_s1ap_unpack_enb_statustransfer_transparentcontainer(ptr, &msg->eNB_StatusTransfer_TransparentContainer) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TraceStart STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracestart(
  LIBLTE_S1AP_MESSAGE_TRACESTART_STRUCT                              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TraceStartIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TraceActivation
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_traceactivation(&msg->TraceActivation, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TRACEACTIVATION,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tracestart(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TRACESTART_STRUCT                              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TraceStartIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TRACEACTIVATION == ie_id) {
        if(liblte_s1ap_unpack_traceactivation(ptr, &msg->TraceActivation) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TraceFailureIndication STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_tracefailureindication(
  LIBLTE_S1AP_MESSAGE_TRACEFAILUREINDICATION_STRUCT                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TraceFailureIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_UTRAN_Trace_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_utran_trace_id(&msg->E_UTRAN_Trace_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_UTRAN_TRACE_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_tracefailureindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TRACEFAILUREINDICATION_STRUCT                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TraceFailureIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_UTRAN_TRACE_ID == ie_id) {
        if(liblte_s1ap_unpack_e_utran_trace_id(ptr, &msg->E_UTRAN_Trace_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message DeactivateTrace STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_deactivatetrace(
  LIBLTE_S1AP_MESSAGE_DEACTIVATETRACE_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DeactivateTraceIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_UTRAN_Trace_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_utran_trace_id(&msg->E_UTRAN_Trace_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_UTRAN_TRACE_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_deactivatetrace(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_DEACTIVATETRACE_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DeactivateTraceIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_UTRAN_TRACE_ID == ie_id) {
        if(liblte_s1ap_unpack_e_utran_trace_id(ptr, &msg->E_UTRAN_Trace_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message CellTrafficTrace STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_celltraffictrace(
  LIBLTE_S1AP_MESSAGE_CELLTRAFFICTRACE_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellTrafficTraceIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 6;
    if(!msg->PrivacyIndicator_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_UTRAN_Trace_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_utran_trace_id(&msg->E_UTRAN_Trace_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_UTRAN_TRACE_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - EUTRAN_CGI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_EUTRAN_CGI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TraceCollectionEntityIPAddress
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_transportlayeraddress(&msg->TraceCollectionEntityIPAddress, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TRACECOLLECTIONENTITYIPADDRESS,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - PrivacyIndicator
    if(msg->PrivacyIndicator_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_privacyindicator(&msg->PrivacyIndicator, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_PRIVACYINDICATOR,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_celltraffictrace(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_CELLTRAFFICTRACE_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->PrivacyIndicator_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("CellTrafficTraceIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_UTRAN_TRACE_ID == ie_id) {
        if(liblte_s1ap_unpack_e_utran_trace_id(ptr, &msg->E_UTRAN_Trace_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_EUTRAN_CGI == ie_id) {
        if(liblte_s1ap_unpack_eutran_cgi(ptr, &msg->EUTRAN_CGI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TRACECOLLECTIONENTITYIPADDRESS == ie_id) {
        if(liblte_s1ap_unpack_transportlayeraddress(ptr, &msg->TraceCollectionEntityIPAddress) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_PRIVACYINDICATOR == ie_id) {
        if(liblte_s1ap_unpack_privacyindicator(ptr, &msg->PrivacyIndicator) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->PrivacyIndicator_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message LocationReportingControl STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingcontrol(
  LIBLTE_S1AP_MESSAGE_LOCATIONREPORTINGCONTROL_STRUCT                *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LocationReportingControlIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - RequestType
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_requesttype(&msg->RequestType, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_REQUESTTYPE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_locationreportingcontrol(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_LOCATIONREPORTINGCONTROL_STRUCT                *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LocationReportingControlIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_REQUESTTYPE == ie_id) {
        if(liblte_s1ap_unpack_requesttype(ptr, &msg->RequestType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message LocationReportingFailureIndication STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreportingfailureindication(
  LIBLTE_S1AP_MESSAGE_LOCATIONREPORTINGFAILUREINDICATION_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LocationReportingFailureIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_locationreportingfailureindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_LOCATIONREPORTINGFAILUREINDICATION_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LocationReportingFailureIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message LocationReport STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_locationreport(
  LIBLTE_S1AP_MESSAGE_LOCATIONREPORT_STRUCT                          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LocationReportIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 5;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - EUTRAN_CGI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_EUTRAN_CGI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TAI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TAI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - RequestType
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_requesttype(&msg->RequestType, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_REQUESTTYPE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_locationreport(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_LOCATIONREPORT_STRUCT                          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("LocationReportIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_EUTRAN_CGI == ie_id) {
        if(liblte_s1ap_unpack_eutran_cgi(ptr, &msg->EUTRAN_CGI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TAI == ie_id) {
        if(liblte_s1ap_unpack_tai(ptr, &msg->TAI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_REQUESTTYPE == ie_id) {
        if(liblte_s1ap_unpack_requesttype(ptr, &msg->RequestType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message OverloadStart STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstart(
  LIBLTE_S1AP_MESSAGE_OVERLOADSTART_STRUCT                           *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("OverloadStartIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 3;
    if(!msg->GUMMEIList_present)
      n_ie--;
    if(!msg->TrafficLoadReductionIndication_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - OverloadResponse
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_overloadresponse(&msg->OverloadResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_OVERLOADRESPONSE,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - GUMMEIList
    if(msg->GUMMEIList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_gummeilist(&msg->GUMMEIList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_GUMMEILIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - TrafficLoadReductionIndication
    if(msg->TrafficLoadReductionIndication_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_trafficloadreductionindication(&msg->TrafficLoadReductionIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TRAFFICLOADREDUCTIONINDICATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_overloadstart(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_OVERLOADSTART_STRUCT                           *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->GUMMEIList_present = false;
    msg->TrafficLoadReductionIndication_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("OverloadStartIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_OVERLOADRESPONSE == ie_id) {
        if(liblte_s1ap_unpack_overloadresponse(ptr, &msg->OverloadResponse) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_GUMMEILIST == ie_id) {
        if(liblte_s1ap_unpack_gummeilist(ptr, &msg->GUMMEIList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->GUMMEIList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_TRAFFICLOADREDUCTIONINDICATION == ie_id) {
        if(liblte_s1ap_unpack_trafficloadreductionindication(ptr, &msg->TrafficLoadReductionIndication) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->TrafficLoadReductionIndication_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message OverloadStop STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_overloadstop(
  LIBLTE_S1AP_MESSAGE_OVERLOADSTOP_STRUCT                            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("OverloadStopIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->GUMMEIList_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - GUMMEIList
    if(msg->GUMMEIList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_gummeilist(&msg->GUMMEIList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_GUMMEILIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_overloadstop(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_OVERLOADSTOP_STRUCT                            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->GUMMEIList_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("OverloadStopIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_GUMMEILIST == ie_id) {
        if(liblte_s1ap_unpack_gummeilist(ptr, &msg->GUMMEIList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->GUMMEIList_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message WriteReplaceWarningRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningrequest(
  LIBLTE_S1AP_MESSAGE_WRITEREPLACEWARNINGREQUEST_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("WriteReplaceWarningRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 11;
    if(!msg->WarningAreaList_present)
      n_ie--;
    if(!msg->ExtendedRepetitionPeriod_present)
      n_ie--;
    if(!msg->WarningType_present)
      n_ie--;
    if(!msg->WarningSecurityInfo_present)
      n_ie--;
    if(!msg->DataCodingScheme_present)
      n_ie--;
    if(!msg->WarningMessageContents_present)
      n_ie--;
    if(!msg->ConcurrentWarningMessageIndicator_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MessageIdentifier
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MESSAGEIDENTIFIER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - SerialNumber
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SERIALNUMBER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - WarningAreaList
    if(msg->WarningAreaList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_warningarealist(&msg->WarningAreaList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_WARNINGAREALIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - RepetitionPeriod
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_repetitionperiod(&msg->RepetitionPeriod, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_REPETITIONPERIOD,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - ExtendedRepetitionPeriod
    if(msg->ExtendedRepetitionPeriod_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_extendedrepetitionperiod(&msg->ExtendedRepetitionPeriod, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_EXTENDEDREPETITIONPERIOD,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - NumberofBroadcastRequest
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_numberofbroadcastrequest(&msg->NumberofBroadcastRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_NUMBEROFBROADCASTREQUEST,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - WarningType
    if(msg->WarningType_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_warningtype(&msg->WarningType, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_WARNINGTYPE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - WarningSecurityInfo
    if(msg->WarningSecurityInfo_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_warningsecurityinfo(&msg->WarningSecurityInfo, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_WARNINGSECURITYINFO,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - DataCodingScheme
    if(msg->DataCodingScheme_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_datacodingscheme(&msg->DataCodingScheme, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_DATACODINGSCHEME,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - WarningMessageContents
    if(msg->WarningMessageContents_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_warningmessagecontents(&msg->WarningMessageContents, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_WARNINGMESSAGECONTENTS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - ConcurrentWarningMessageIndicator
    if(msg->ConcurrentWarningMessageIndicator_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_concurrentwarningmessageindicator(&msg->ConcurrentWarningMessageIndicator, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CONCURRENTWARNINGMESSAGEINDICATOR,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_writereplacewarningrequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_WRITEREPLACEWARNINGREQUEST_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->WarningAreaList_present = false;
    msg->ExtendedRepetitionPeriod_present = false;
    msg->WarningType_present = false;
    msg->WarningSecurityInfo_present = false;
    msg->DataCodingScheme_present = false;
    msg->WarningMessageContents_present = false;
    msg->ConcurrentWarningMessageIndicator_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("WriteReplaceWarningRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MESSAGEIDENTIFIER == ie_id) {
        if(liblte_s1ap_unpack_messageidentifier(ptr, &msg->MessageIdentifier) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_SERIALNUMBER == ie_id) {
        if(liblte_s1ap_unpack_serialnumber(ptr, &msg->SerialNumber) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_WARNINGAREALIST == ie_id) {
        if(liblte_s1ap_unpack_warningarealist(ptr, &msg->WarningAreaList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->WarningAreaList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_REPETITIONPERIOD == ie_id) {
        if(liblte_s1ap_unpack_repetitionperiod(ptr, &msg->RepetitionPeriod) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_EXTENDEDREPETITIONPERIOD == ie_id) {
        if(liblte_s1ap_unpack_extendedrepetitionperiod(ptr, &msg->ExtendedRepetitionPeriod) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->ExtendedRepetitionPeriod_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_NUMBEROFBROADCASTREQUEST == ie_id) {
        if(liblte_s1ap_unpack_numberofbroadcastrequest(ptr, &msg->NumberofBroadcastRequest) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_WARNINGTYPE == ie_id) {
        if(liblte_s1ap_unpack_warningtype(ptr, &msg->WarningType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->WarningType_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_WARNINGSECURITYINFO == ie_id) {
        if(liblte_s1ap_unpack_warningsecurityinfo(ptr, &msg->WarningSecurityInfo) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->WarningSecurityInfo_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_DATACODINGSCHEME == ie_id) {
        if(liblte_s1ap_unpack_datacodingscheme(ptr, &msg->DataCodingScheme) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->DataCodingScheme_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_WARNINGMESSAGECONTENTS == ie_id) {
        if(liblte_s1ap_unpack_warningmessagecontents(ptr, &msg->WarningMessageContents) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->WarningMessageContents_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CONCURRENTWARNINGMESSAGEINDICATOR == ie_id) {
        if(liblte_s1ap_unpack_concurrentwarningmessageindicator(ptr, &msg->ConcurrentWarningMessageIndicator) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->ConcurrentWarningMessageIndicator_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message WriteReplaceWarningResponse STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_writereplacewarningresponse(
  LIBLTE_S1AP_MESSAGE_WRITEREPLACEWARNINGRESPONSE_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("WriteReplaceWarningResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->BroadcastCompletedAreaList_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MessageIdentifier
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MESSAGEIDENTIFIER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - SerialNumber
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SERIALNUMBER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - BroadcastCompletedAreaList
    if(msg->BroadcastCompletedAreaList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_broadcastcompletedarealist(&msg->BroadcastCompletedAreaList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_BROADCASTCOMPLETEDAREALIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_writereplacewarningresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_WRITEREPLACEWARNINGRESPONSE_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->BroadcastCompletedAreaList_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("WriteReplaceWarningResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MESSAGEIDENTIFIER == ie_id) {
        if(liblte_s1ap_unpack_messageidentifier(ptr, &msg->MessageIdentifier) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_SERIALNUMBER == ie_id) {
        if(liblte_s1ap_unpack_serialnumber(ptr, &msg->SerialNumber) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_BROADCASTCOMPLETEDAREALIST == ie_id) {
        if(liblte_s1ap_unpack_broadcastcompletedarealist(ptr, &msg->BroadcastCompletedAreaList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->BroadcastCompletedAreaList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message MMEDirectInformationTransfer STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmedirectinformationtransfer(
  LIBLTE_S1AP_MESSAGE_MMEDIRECTINFORMATIONTRANSFER_STRUCT            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEDirectInformationTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Inter_SystemInformationTransferTypeMDT
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_inter_systeminformationtransfertype(&msg->Inter_SystemInformationTransferTypeMDT, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_INTER_SYSTEMINFORMATIONTRANSFERTYPEMDT,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mmedirectinformationtransfer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_MMEDIRECTINFORMATIONTRANSFER_STRUCT            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEDirectInformationTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_INTER_SYSTEMINFORMATIONTRANSFERTYPEMDT == ie_id) {
        if(liblte_s1ap_unpack_inter_systeminformationtransfertype(ptr, &msg->Inter_SystemInformationTransferTypeMDT) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ENBConfigurationTransfer STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbconfigurationtransfer(
  LIBLTE_S1AP_MESSAGE_ENBCONFIGURATIONTRANSFER_STRUCT                *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBConfigurationTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->SONConfigurationTransferECT_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - SONConfigurationTransferECT
    if(msg->SONConfigurationTransferECT_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_sonconfigurationtransfer(&msg->SONConfigurationTransferECT, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SONCONFIGURATIONTRANSFERECT,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbconfigurationtransfer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ENBCONFIGURATIONTRANSFER_STRUCT                *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->SONConfigurationTransferECT_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBConfigurationTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_SONCONFIGURATIONTRANSFERECT == ie_id) {
        if(liblte_s1ap_unpack_sonconfigurationtransfer(ptr, &msg->SONConfigurationTransferECT) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SONConfigurationTransferECT_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message MMEConfigurationTransfer STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_mmeconfigurationtransfer(
  LIBLTE_S1AP_MESSAGE_MMECONFIGURATIONTRANSFER_STRUCT                *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEConfigurationTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    if(!msg->SONConfigurationTransferMCT_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - SONConfigurationTransferMCT
    if(msg->SONConfigurationTransferMCT_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_sonconfigurationtransfer(&msg->SONConfigurationTransferMCT, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SONCONFIGURATIONTRANSFERMCT,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_mmeconfigurationtransfer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_MMECONFIGURATIONTRANSFER_STRUCT                *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->SONConfigurationTransferMCT_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("MMEConfigurationTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_SONCONFIGURATIONTRANSFERMCT == ie_id) {
        if(liblte_s1ap_unpack_sonconfigurationtransfer(ptr, &msg->SONConfigurationTransferMCT) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SONConfigurationTransferMCT_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message PrivateMessage STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_privatemessage(
  LIBLTE_S1AP_MESSAGE_PRIVATEMESSAGE_STRUCT                          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PrivateMessageIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 0;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_privatemessage(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_PRIVATEMESSAGE_STRUCT                          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PrivateMessageIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);


    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message KillRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_killrequest(
  LIBLTE_S1AP_MESSAGE_KILLREQUEST_STRUCT                             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("KillRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->WarningAreaList_present)
      n_ie--;
    if(!msg->KillAllWarningMessages_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MessageIdentifier
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MESSAGEIDENTIFIER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - SerialNumber
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SERIALNUMBER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - WarningAreaList
    if(msg->WarningAreaList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_warningarealist(&msg->WarningAreaList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_WARNINGAREALIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - KillAllWarningMessages
    if(msg->KillAllWarningMessages_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_killallwarningmessages(&msg->KillAllWarningMessages, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_KILLALLWARNINGMESSAGES,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_killrequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_KILLREQUEST_STRUCT                             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->WarningAreaList_present = false;
    msg->KillAllWarningMessages_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("KillRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MESSAGEIDENTIFIER == ie_id) {
        if(liblte_s1ap_unpack_messageidentifier(ptr, &msg->MessageIdentifier) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_SERIALNUMBER == ie_id) {
        if(liblte_s1ap_unpack_serialnumber(ptr, &msg->SerialNumber) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_WARNINGAREALIST == ie_id) {
        if(liblte_s1ap_unpack_warningarealist(ptr, &msg->WarningAreaList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->WarningAreaList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_KILLALLWARNINGMESSAGES == ie_id) {
        if(liblte_s1ap_unpack_killallwarningmessages(ptr, &msg->KillAllWarningMessages) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->KillAllWarningMessages_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message KillResponse STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_killresponse(
  LIBLTE_S1AP_MESSAGE_KILLRESPONSE_STRUCT                            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("KillResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->BroadcastCancelledAreaList_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MessageIdentifier
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_messageidentifier(&msg->MessageIdentifier, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MESSAGEIDENTIFIER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - SerialNumber
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_serialnumber(&msg->SerialNumber, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SERIALNUMBER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - BroadcastCancelledAreaList
    if(msg->BroadcastCancelledAreaList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_broadcastcancelledarealist(&msg->BroadcastCancelledAreaList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_BROADCASTCANCELLEDAREALIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_killresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_KILLRESPONSE_STRUCT                            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->BroadcastCancelledAreaList_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("KillResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MESSAGEIDENTIFIER == ie_id) {
        if(liblte_s1ap_unpack_messageidentifier(ptr, &msg->MessageIdentifier) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_SERIALNUMBER == ie_id) {
        if(liblte_s1ap_unpack_serialnumber(ptr, &msg->SerialNumber) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_BROADCASTCANCELLEDAREALIST == ie_id) {
        if(liblte_s1ap_unpack_broadcastcancelledarealist(ptr, &msg->BroadcastCancelledAreaList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->BroadcastCancelledAreaList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message PWSRestartIndication STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pwsrestartindication(
  LIBLTE_S1AP_MESSAGE_PWSRESTARTINDICATION_STRUCT                    *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PWSRestartIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->EmergencyAreaIDListForRestart_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - ECGIListForRestart
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_ecgilistforrestart(&msg->ECGIListForRestart, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ECGILISTFORRESTART,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Global_ENB_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_global_enb_id(&msg->Global_ENB_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_GLOBAL_ENB_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TAIListForRestart
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_tailistforrestart(&msg->TAIListForRestart, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TAILISTFORRESTART,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - EmergencyAreaIDListForRestart
    if(msg->EmergencyAreaIDListForRestart_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_emergencyareaidlistforrestart(&msg->EmergencyAreaIDListForRestart, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_EMERGENCYAREAIDLISTFORRESTART,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pwsrestartindication(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_PWSRESTARTINDICATION_STRUCT                    *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->EmergencyAreaIDListForRestart_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PWSRestartIndicationIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_ECGILISTFORRESTART == ie_id) {
        if(liblte_s1ap_unpack_ecgilistforrestart(ptr, &msg->ECGIListForRestart) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_GLOBAL_ENB_ID == ie_id) {
        if(liblte_s1ap_unpack_global_enb_id(ptr, &msg->Global_ENB_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TAILISTFORRESTART == ie_id) {
        if(liblte_s1ap_unpack_tailistforrestart(ptr, &msg->TAIListForRestart) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_EMERGENCYAREAIDLISTFORRESTART == ie_id) {
        if(liblte_s1ap_unpack_emergencyareaidlistforrestart(ptr, &msg->EmergencyAreaIDListForRestart) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->EmergencyAreaIDListForRestart_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message DownlinkUEAssociatedLPPaTransport STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinkueassociatedlppatransport(
  LIBLTE_S1AP_MESSAGE_DOWNLINKUEASSOCIATEDLPPATRANSPORT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DownlinkUEAssociatedLPPaTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Routing_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ROUTING_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - LPPa_PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_LPPA_PDU,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_downlinkueassociatedlppatransport(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_DOWNLINKUEASSOCIATEDLPPATRANSPORT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DownlinkUEAssociatedLPPaTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ROUTING_ID == ie_id) {
        if(liblte_s1ap_unpack_routing_id(ptr, &msg->Routing_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_LPPA_PDU == ie_id) {
        if(liblte_s1ap_unpack_lppa_pdu(ptr, &msg->LPPa_PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UplinkUEAssociatedLPPaTransport STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinkueassociatedlppatransport(
  LIBLTE_S1AP_MESSAGE_UPLINKUEASSOCIATEDLPPATRANSPORT_STRUCT         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UplinkUEAssociatedLPPaTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Routing_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ROUTING_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - LPPa_PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_LPPA_PDU,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uplinkueassociatedlppatransport(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UPLINKUEASSOCIATEDLPPATRANSPORT_STRUCT         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UplinkUEAssociatedLPPaTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ROUTING_ID == ie_id) {
        if(liblte_s1ap_unpack_routing_id(ptr, &msg->Routing_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_LPPA_PDU == ie_id) {
        if(liblte_s1ap_unpack_lppa_pdu(ptr, &msg->LPPa_PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message DownlinkNonUEAssociatedLPPaTransport STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinknonueassociatedlppatransport(
  LIBLTE_S1AP_MESSAGE_DOWNLINKNONUEASSOCIATEDLPPATRANSPORT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DownlinkNonUEAssociatedLPPaTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 2;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Routing_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ROUTING_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - LPPa_PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_LPPA_PDU,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_downlinknonueassociatedlppatransport(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_DOWNLINKNONUEASSOCIATEDLPPATRANSPORT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DownlinkNonUEAssociatedLPPaTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_ROUTING_ID == ie_id) {
        if(liblte_s1ap_unpack_routing_id(ptr, &msg->Routing_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_LPPA_PDU == ie_id) {
        if(liblte_s1ap_unpack_lppa_pdu(ptr, &msg->LPPa_PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message UplinkNonUEAssociatedLPPaTransport STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_uplinknonueassociatedlppatransport(
  LIBLTE_S1AP_MESSAGE_UPLINKNONUEASSOCIATEDLPPATRANSPORT_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UplinkNonUEAssociatedLPPaTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 2;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Routing_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_routing_id(&msg->Routing_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ROUTING_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - LPPa_PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_lppa_pdu(&msg->LPPa_PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_LPPA_PDU,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_uplinknonueassociatedlppatransport(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_UPLINKNONUEASSOCIATEDLPPATRANSPORT_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("UplinkNonUEAssociatedLPPaTransport-IEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_ROUTING_ID == ie_id) {
        if(liblte_s1ap_unpack_routing_id(ptr, &msg->Routing_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_LPPA_PDU == ie_id) {
        if(liblte_s1ap_unpack_lppa_pdu(ptr, &msg->LPPa_PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ENBDirectInformationTransfer STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_enbdirectinformationtransfer(
  LIBLTE_S1AP_MESSAGE_ENBDIRECTINFORMATIONTRANSFER_STRUCT            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBDirectInformationTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Inter_SystemInformationTransferTypeEDT
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_inter_systeminformationtransfertype(&msg->Inter_SystemInformationTransferTypeEDT, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_INTER_SYSTEMINFORMATIONTRANSFERTYPEEDT,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_enbdirectinformationtransfer(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_ENBDIRECTINFORMATIONTRANSFER_STRUCT            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ENBDirectInformationTransferIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_INTER_SYSTEMINFORMATIONTRANSFERTYPEEDT == ie_id) {
        if(liblte_s1ap_unpack_inter_systeminformationtransfertype(ptr, &msg->Inter_SystemInformationTransferTypeEDT) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABDataForwardingItem STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabdataforwardingitem(
  LIBLTE_S1AP_MESSAGE_E_RABDATAFORWARDINGITEM_STRUCT                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABDataForwardingItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABDataForwardingItem
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabdataforwardingitem(&msg->E_RABDataForwardingItem, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABDATAFORWARDINGITEM,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabdataforwardingitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABDATAFORWARDINGITEM_STRUCT                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABDataForwardingItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABDATAFORWARDINGITEM == ie_id) {
        if(liblte_s1ap_unpack_e_rabdataforwardingitem(ptr, &msg->E_RABDataForwardingItem) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSetupItemHOReq STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemhoreq(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMHOREQ_STRUCT                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemHOReqIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABToBeSetupItemHOReq
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobesetupitemhoreq(&msg->E_RABToBeSetupItemHOReq, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMHOREQ,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetupitemhoreq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMHOREQ_STRUCT                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemHOReqIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMHOREQ == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobesetupitemhoreq(ptr, &msg->E_RABToBeSetupItemHOReq) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABAdmittedItem STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabadmitteditem(
  LIBLTE_S1AP_MESSAGE_E_RABADMITTEDITEM_STRUCT                       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABAdmittedItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABAdmittedItem
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabadmitteditem(&msg->E_RABAdmittedItem, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABADMITTEDITEM,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabadmitteditem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABADMITTEDITEM_STRUCT                       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABAdmittedItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABADMITTEDITEM == ie_id) {
        if(liblte_s1ap_unpack_e_rabadmitteditem(ptr, &msg->E_RABAdmittedItem) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABFailedtoSetupItemHOReqAck STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack(
  LIBLTE_S1AP_MESSAGE_E_RABFAILEDTOSETUPITEMHOREQACK_STRUCT          *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABFailedtoSetupItemHOReqAckIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABFailedtoSetupItemHOReqAck
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabfailedtosetupitemhoreqack(&msg->E_RABFailedtoSetupItemHOReqAck, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPITEMHOREQACK,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabfailedtosetupitemhoreqack(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABFAILEDTOSETUPITEMHOREQACK_STRUCT          *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABFailedtoSetupItemHOReqAckIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPITEMHOREQACK == ie_id) {
        if(liblte_s1ap_unpack_e_rabfailedtosetupitemhoreqack(ptr, &msg->E_RABFailedtoSetupItemHOReqAck) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSwitchedDLItem STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitcheddlitem(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESWITCHEDDLITEM_STRUCT                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSwitchedDLItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABToBeSwitchedDLItem
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobeswitcheddlitem(&msg->E_RABToBeSwitchedDLItem, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDDLITEM,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobeswitcheddlitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESWITCHEDDLITEM_STRUCT                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSwitchedDLItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDDLITEM == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobeswitcheddlitem(ptr, &msg->E_RABToBeSwitchedDLItem) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSwitchedULItem STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobeswitchedulitem(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESWITCHEDULITEM_STRUCT                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSwitchedULItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABToBeSwitchedULItem
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobeswitchedulitem(&msg->E_RABToBeSwitchedULItem, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDULITEM,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobeswitchedulitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESWITCHEDULITEM_STRUCT                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSwitchedULItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDULITEM == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobeswitchedulitem(ptr, &msg->E_RABToBeSwitchedULItem) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSetupItemBearerSUReq STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitembearersureq(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMBEARERSUREQ_STRUCT           *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemBearerSUReqIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABToBeSetupItemBearerSUReq
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobesetupitembearersureq(&msg->E_RABToBeSetupItemBearerSUReq, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMBEARERSUREQ,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetupitembearersureq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMBEARERSUREQ_STRUCT           *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemBearerSUReqIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMBEARERSUREQ == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobesetupitembearersureq(ptr, &msg->E_RABToBeSetupItemBearerSUReq) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABSetupItemBearerSURes STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitembearersures(
  LIBLTE_S1AP_MESSAGE_E_RABSETUPITEMBEARERSURES_STRUCT               *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupItemBearerSUResIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABSetupItemBearerSURes
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabsetupitembearersures(&msg->E_RABSetupItemBearerSURes, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABSETUPITEMBEARERSURES,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetupitembearersures(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABSETUPITEMBEARERSURES_STRUCT               *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupItemBearerSUResIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABSETUPITEMBEARERSURES == ie_id) {
        if(liblte_s1ap_unpack_e_rabsetupitembearersures(ptr, &msg->E_RABSetupItemBearerSURes) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeModifiedItemBearerModReq STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobemodifieditembearermodreq(
  LIBLTE_S1AP_MESSAGE_E_RABTOBEMODIFIEDITEMBEARERMODREQ_STRUCT       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeModifiedItemBearerModReqIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABToBeModifiedItemBearerModReq
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobemodifieditembearermodreq(&msg->E_RABToBeModifiedItemBearerModReq, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBEMODIFIEDITEMBEARERMODREQ,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobemodifieditembearermodreq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBEMODIFIEDITEMBEARERMODREQ_STRUCT       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeModifiedItemBearerModReqIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBEMODIFIEDITEMBEARERMODREQ == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobemodifieditembearermodreq(ptr, &msg->E_RABToBeModifiedItemBearerModReq) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABModifyItemBearerModRes STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyitembearermodres(
  LIBLTE_S1AP_MESSAGE_E_RABMODIFYITEMBEARERMODRES_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABModifyItemBearerModResIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABModifyItemBearerModRes
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabmodifyitembearermodres(&msg->E_RABModifyItemBearerModRes, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABMODIFYITEMBEARERMODRES,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabmodifyitembearermodres(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABMODIFYITEMBEARERMODRES_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABModifyItemBearerModResIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABMODIFYITEMBEARERMODRES == ie_id) {
        if(liblte_s1ap_unpack_e_rabmodifyitembearermodres(ptr, &msg->E_RABModifyItemBearerModRes) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABReleaseItemBearerRelComp STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseitembearerrelcomp(
  LIBLTE_S1AP_MESSAGE_E_RABRELEASEITEMBEARERRELCOMP_STRUCT           *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseItemBearerRelCompIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABReleaseItemBearerRelComp
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabreleaseitembearerrelcomp(&msg->E_RABReleaseItemBearerRelComp, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABRELEASEITEMBEARERRELCOMP,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabreleaseitembearerrelcomp(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABRELEASEITEMBEARERRELCOMP_STRUCT           *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseItemBearerRelCompIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABRELEASEITEMBEARERRELCOMP == ie_id) {
        if(liblte_s1ap_unpack_e_rabreleaseitembearerrelcomp(ptr, &msg->E_RABReleaseItemBearerRelComp) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABToBeSetupItemCtxtSUReq STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabtobesetupitemctxtsureq(
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemCtxtSUReqIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABToBeSetupItemCtxtSUReq
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobesetupitemctxtsureq(&msg->E_RABToBeSetupItemCtxtSUReq, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMCTXTSUREQ,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabtobesetupitemctxtsureq(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABToBeSetupItemCtxtSUReqIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABTOBESETUPITEMCTXTSUREQ == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobesetupitemctxtsureq(ptr, &msg->E_RABToBeSetupItemCtxtSUReq) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABSetupItemCtxtSURes STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupitemctxtsures(
  LIBLTE_S1AP_MESSAGE_E_RABSETUPITEMCTXTSURES_STRUCT                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupItemCtxtSUResIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - E_RABSetupItemCtxtSURes
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabsetupitemctxtsures(&msg->E_RABSetupItemCtxtSURes, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABSETUPITEMCTXTSURES,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetupitemctxtsures(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABSETUPITEMCTXTSURES_STRUCT                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupItemCtxtSUResIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_E_RABSETUPITEMCTXTSURES == ie_id) {
        if(liblte_s1ap_unpack_e_rabsetupitemctxtsures(ptr, &msg->E_RABSetupItemCtxtSURes) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message TAIItem STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_taiitem(
  LIBLTE_S1AP_MESSAGE_TAIITEM_STRUCT                                 *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAIItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 1;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - TAIItem
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_taiitem(&msg->TAIItem, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TAIITEM,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_taiitem(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_TAIITEM_STRUCT                                 *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("TAIItemIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_TAIITEM == ie_id) {
        if(liblte_s1ap_unpack_taiitem(ptr, &msg->TAIItem) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message ResetAcknowledge STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_resetacknowledge(
  LIBLTE_S1AP_MESSAGE_RESETACKNOWLEDGE_STRUCT                        *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ResetAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 2;
    if(!msg->UE_associatedLogicalS1_ConnectionListResAck_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - UE_associatedLogicalS1_ConnectionListResAck
    if(msg->UE_associatedLogicalS1_ConnectionListResAck_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ue_associatedlogicals1_connectionlistresack(&msg->UE_associatedLogicalS1_ConnectionListResAck, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONLISTRESACK,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_resetacknowledge(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_RESETACKNOWLEDGE_STRUCT                        *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->UE_associatedLogicalS1_ConnectionListResAck_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ResetAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_UE_ASSOCIATEDLOGICALS1_CONNECTIONLISTRESACK == ie_id) {
        if(liblte_s1ap_unpack_ue_associatedlogicals1_connectionlistresack(ptr, &msg->UE_associatedLogicalS1_ConnectionListResAck) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->UE_associatedLogicalS1_ConnectionListResAck_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message Reset STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_reset(
  LIBLTE_S1AP_MESSAGE_RESET_STRUCT                                   *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ResetIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 2;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - ResetType
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_resettype(&msg->ResetType, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_RESETTYPE,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_reset(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_RESET_STRUCT                                   *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("ResetIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_RESETTYPE == ie_id) {
        if(liblte_s1ap_unpack_resettype(ptr, &msg->ResetType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message DownlinkS1cdma2000tunneling STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_downlinks1cdma2000tunneling(
  LIBLTE_S1AP_MESSAGE_DOWNLINKS1CDMA2000TUNNELING_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DownlinkS1cdma2000tunnelingIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 6;
    if(!msg->E_RABSubjecttoDataForwardingList_present)
      n_ie--;
    if(!msg->cdma2000HOStatus_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABSubjecttoDataForwardingList
    if(msg->E_RABSubjecttoDataForwardingList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabsubjecttodataforwardinglist(&msg->E_RABSubjecttoDataForwardingList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABSUBJECTTODATAFORWARDINGLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - cdma2000HOStatus
    if(msg->cdma2000HOStatus_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cdma2000hostatus(&msg->cdma2000HOStatus, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CDMA2000HOSTATUS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - cdma2000RATType
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cdma2000rattype(&msg->cdma2000RATType, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CDMA2000RATTYPE,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - cdma2000PDU
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cdma2000pdu(&msg->cdma2000PDU, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CDMA2000PDU,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_downlinks1cdma2000tunneling(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_DOWNLINKS1CDMA2000TUNNELING_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->E_RABSubjecttoDataForwardingList_present = false;
    msg->cdma2000HOStatus_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("DownlinkS1cdma2000tunnelingIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABSUBJECTTODATAFORWARDINGLIST == ie_id) {
        if(liblte_s1ap_unpack_e_rabsubjecttodataforwardinglist(ptr, &msg->E_RABSubjecttoDataForwardingList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABSubjecttoDataForwardingList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CDMA2000HOSTATUS == ie_id) {
        if(liblte_s1ap_unpack_cdma2000hostatus(ptr, &msg->cdma2000HOStatus) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->cdma2000HOStatus_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CDMA2000RATTYPE == ie_id) {
        if(liblte_s1ap_unpack_cdma2000rattype(ptr, &msg->cdma2000RATType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CDMA2000PDU == ie_id) {
        if(liblte_s1ap_unpack_cdma2000pdu(ptr, &msg->cdma2000PDU) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverCommand STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handovercommand(
  LIBLTE_S1AP_MESSAGE_HANDOVERCOMMAND_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverCommandIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 9;
    if(!msg->NASSecurityParametersfromE_UTRAN_present)
      n_ie--;
    if(!msg->E_RABSubjecttoDataForwardingList_present)
      n_ie--;
    if(!msg->E_RABtoReleaseListHOCmd_present)
      n_ie--;
    if(!msg->Target_ToSource_TransparentContainer_Secondary_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - HandoverType
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_handovertype(&msg->HandoverType, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_HANDOVERTYPE,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - NASSecurityParametersfromE_UTRAN
    if(msg->NASSecurityParametersfromE_UTRAN_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_nassecurityparametersfrome_utran(&msg->NASSecurityParametersfromE_UTRAN, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_NASSECURITYPARAMETERSFROME_UTRAN,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABSubjecttoDataForwardingList
    if(msg->E_RABSubjecttoDataForwardingList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabsubjecttodataforwardinglist(&msg->E_RABSubjecttoDataForwardingList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABSUBJECTTODATAFORWARDINGLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABtoReleaseListHOCmd
    if(msg->E_RABtoReleaseListHOCmd_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rablist(&msg->E_RABtoReleaseListHOCmd, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABTORELEASELISTHOCMD,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - Target_ToSource_TransparentContainer
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_target_tosource_transparentcontainer(&msg->Target_ToSource_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TARGET_TOSOURCE_TRANSPARENTCONTAINER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Target_ToSource_TransparentContainer_Secondary
    if(msg->Target_ToSource_TransparentContainer_Secondary_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_target_tosource_transparentcontainer(&msg->Target_ToSource_TransparentContainer_Secondary, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TARGET_TOSOURCE_TRANSPARENTCONTAINER_SECONDARY,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handovercommand(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERCOMMAND_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->NASSecurityParametersfromE_UTRAN_present = false;
    msg->E_RABSubjecttoDataForwardingList_present = false;
    msg->E_RABtoReleaseListHOCmd_present = false;
    msg->Target_ToSource_TransparentContainer_Secondary_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverCommandIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_HANDOVERTYPE == ie_id) {
        if(liblte_s1ap_unpack_handovertype(ptr, &msg->HandoverType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_NASSECURITYPARAMETERSFROME_UTRAN == ie_id) {
        if(liblte_s1ap_unpack_nassecurityparametersfrome_utran(ptr, &msg->NASSecurityParametersfromE_UTRAN) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABSUBJECTTODATAFORWARDINGLIST == ie_id) {
        if(liblte_s1ap_unpack_e_rabsubjecttodataforwardinglist(ptr, &msg->E_RABSubjecttoDataForwardingList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABSubjecttoDataForwardingList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_E_RABTORELEASELISTHOCMD == ie_id) {
        if(liblte_s1ap_unpack_e_rablist(ptr, &msg->E_RABtoReleaseListHOCmd) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABtoReleaseListHOCmd_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_TARGET_TOSOURCE_TRANSPARENTCONTAINER == ie_id) {
        if(liblte_s1ap_unpack_target_tosource_transparentcontainer(ptr, &msg->Target_ToSource_TransparentContainer) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TARGET_TOSOURCE_TRANSPARENTCONTAINER_SECONDARY == ie_id) {
        if(liblte_s1ap_unpack_target_tosource_transparentcontainer(ptr, &msg->Target_ToSource_TransparentContainer_Secondary) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Target_ToSource_TransparentContainer_Secondary_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequest(
  LIBLTE_S1AP_MESSAGE_HANDOVERREQUEST_STRUCT                         *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 19;
    if(!msg->HandoverRestrictionList_present)
      n_ie--;
    if(!msg->TraceActivation_present)
      n_ie--;
    if(!msg->RequestType_present)
      n_ie--;
    if(!msg->SRVCCOperationPossible_present)
      n_ie--;
    if(!msg->NASSecurityParameterstoE_UTRAN_present)
      n_ie--;
    if(!msg->CSG_Id_present)
      n_ie--;
    if(!msg->CSGMembershipStatus_present)
      n_ie--;
    if(!msg->GUMMEI_ID_present)
      n_ie--;
    if(!msg->MME_UE_S1AP_ID_2_present)
      n_ie--;
    if(!msg->ManagementBasedMDTAllowed_present)
      n_ie--;
    if(!msg->ManagementBasedMDTPLMNList_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - HandoverType
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_handovertype(&msg->HandoverType, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_HANDOVERTYPE,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Cause
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cause(&msg->Cause, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CAUSE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - uEaggregateMaximumBitrate
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABToBeSetupListHOReq
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobesetuplisthoreq(&msg->E_RABToBeSetupListHOReq, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBESETUPLISTHOREQ,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - Source_ToTarget_TransparentContainer
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_source_totarget_transparentcontainer(&msg->Source_ToTarget_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SOURCE_TOTARGET_TRANSPARENTCONTAINER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - UESecurityCapabilities
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UESECURITYCAPABILITIES,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - HandoverRestrictionList
    if(msg->HandoverRestrictionList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_handoverrestrictionlist(&msg->HandoverRestrictionList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_HANDOVERRESTRICTIONLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - TraceActivation
    if(msg->TraceActivation_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_traceactivation(&msg->TraceActivation, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TRACEACTIVATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - RequestType
    if(msg->RequestType_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_requesttype(&msg->RequestType, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_REQUESTTYPE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SRVCCOperationPossible
    if(msg->SRVCCOperationPossible_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_srvccoperationpossible(&msg->SRVCCOperationPossible, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SRVCCOPERATIONPOSSIBLE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SecurityContext
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_securitycontext(&msg->SecurityContext, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SECURITYCONTEXT,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - NASSecurityParameterstoE_UTRAN
    if(msg->NASSecurityParameterstoE_UTRAN_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_nassecurityparameterstoe_utran(&msg->NASSecurityParameterstoE_UTRAN, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_NASSECURITYPARAMETERSTOE_UTRAN,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSG_Id
    if(msg->CSG_Id_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSG_ID,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSGMembershipStatus
    if(msg->CSGMembershipStatus_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - GUMMEI_ID
    if(msg->GUMMEI_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_gummei(&msg->GUMMEI_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_GUMMEI_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - MME_UE_S1AP_ID_2
    if(msg->MME_UE_S1AP_ID_2_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID_2, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID_2,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - ManagementBasedMDTAllowed
    if(msg->ManagementBasedMDTAllowed_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_managementbasedmdtallowed(&msg->ManagementBasedMDTAllowed, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MANAGEMENTBASEDMDTALLOWED,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - ManagementBasedMDTPLMNList
    if(msg->ManagementBasedMDTPLMNList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mdtplmnlist(&msg->ManagementBasedMDTPLMNList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MANAGEMENTBASEDMDTPLMNLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handoverrequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERREQUEST_STRUCT                         *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->HandoverRestrictionList_present = false;
    msg->TraceActivation_present = false;
    msg->RequestType_present = false;
    msg->SRVCCOperationPossible_present = false;
    msg->NASSecurityParameterstoE_UTRAN_present = false;
    msg->CSG_Id_present = false;
    msg->CSGMembershipStatus_present = false;
    msg->GUMMEI_ID_present = false;
    msg->MME_UE_S1AP_ID_2_present = false;
    msg->ManagementBasedMDTAllowed_present = false;
    msg->ManagementBasedMDTPLMNList_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_HANDOVERTYPE == ie_id) {
        if(liblte_s1ap_unpack_handovertype(ptr, &msg->HandoverType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CAUSE == ie_id) {
        if(liblte_s1ap_unpack_cause(ptr, &msg->Cause) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE == ie_id) {
        if(liblte_s1ap_unpack_ueaggregatemaximumbitrate(ptr, &msg->uEaggregateMaximumBitrate) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABTOBESETUPLISTHOREQ == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobesetuplisthoreq(ptr, &msg->E_RABToBeSetupListHOReq) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_SOURCE_TOTARGET_TRANSPARENTCONTAINER == ie_id) {
        if(liblte_s1ap_unpack_source_totarget_transparentcontainer(ptr, &msg->Source_ToTarget_TransparentContainer) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UESECURITYCAPABILITIES == ie_id) {
        if(liblte_s1ap_unpack_uesecuritycapabilities(ptr, &msg->UESecurityCapabilities) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_HANDOVERRESTRICTIONLIST == ie_id) {
        if(liblte_s1ap_unpack_handoverrestrictionlist(ptr, &msg->HandoverRestrictionList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->HandoverRestrictionList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_TRACEACTIVATION == ie_id) {
        if(liblte_s1ap_unpack_traceactivation(ptr, &msg->TraceActivation) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->TraceActivation_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_REQUESTTYPE == ie_id) {
        if(liblte_s1ap_unpack_requesttype(ptr, &msg->RequestType) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->RequestType_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SRVCCOPERATIONPOSSIBLE == ie_id) {
        if(liblte_s1ap_unpack_srvccoperationpossible(ptr, &msg->SRVCCOperationPossible) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SRVCCOperationPossible_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SECURITYCONTEXT == ie_id) {
        if(liblte_s1ap_unpack_securitycontext(ptr, &msg->SecurityContext) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_NASSECURITYPARAMETERSTOE_UTRAN == ie_id) {
        if(liblte_s1ap_unpack_nassecurityparameterstoe_utran(ptr, &msg->NASSecurityParameterstoE_UTRAN) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CSG_ID == ie_id) {
        if(liblte_s1ap_unpack_csg_id(ptr, &msg->CSG_Id) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSG_Id_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS == ie_id) {
        if(liblte_s1ap_unpack_csgmembershipstatus(ptr, &msg->CSGMembershipStatus) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSGMembershipStatus_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_GUMMEI_ID == ie_id) {
        if(liblte_s1ap_unpack_gummei(ptr, &msg->GUMMEI_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->GUMMEI_ID_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID_2 == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID_2) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MME_UE_S1AP_ID_2_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_MANAGEMENTBASEDMDTALLOWED == ie_id) {
        if(liblte_s1ap_unpack_managementbasedmdtallowed(ptr, &msg->ManagementBasedMDTAllowed) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->ManagementBasedMDTAllowed_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_MANAGEMENTBASEDMDTPLMNLIST == ie_id) {
        if(liblte_s1ap_unpack_mdtplmnlist(ptr, &msg->ManagementBasedMDTPLMNList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->ManagementBasedMDTPLMNList_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message PathSwitchRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequest(
  LIBLTE_S1AP_MESSAGE_PATHSWITCHREQUEST_STRUCT                       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PathSwitchRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 12;
    if(!msg->CSG_Id_present)
      n_ie--;
    if(!msg->CellAccessMode_present)
      n_ie--;
    if(!msg->SourceMME_GUMMEI_present)
      n_ie--;
    if(!msg->CSGMembershipStatus_present)
      n_ie--;
    if(!msg->Tunnel_Information_for_BBF_present)
      n_ie--;
    if(!msg->LHN_ID_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABToBeSwitchedDLList
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobeswitcheddllist(&msg->E_RABToBeSwitchedDLList, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDDLLIST,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - SourceMME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->SourceMME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SOURCEMME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - EUTRAN_CGI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_eutran_cgi(&msg->EUTRAN_CGI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_EUTRAN_CGI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TAI
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_tai(&msg->TAI, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TAI,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - UESecurityCapabilities
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UESECURITYCAPABILITIES,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CSG_Id
    if(msg->CSG_Id_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSG_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CellAccessMode
    if(msg->CellAccessMode_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CELLACCESSMODE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SourceMME_GUMMEI
    if(msg->SourceMME_GUMMEI_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_gummei(&msg->SourceMME_GUMMEI, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SOURCEMME_GUMMEI,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSGMembershipStatus
    if(msg->CSGMembershipStatus_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - Tunnel_Information_for_BBF
    if(msg->Tunnel_Information_for_BBF_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_tunnelinformation(&msg->Tunnel_Information_for_BBF, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TUNNEL_INFORMATION_FOR_BBF,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - LHN_ID
    if(msg->LHN_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_lhn_id(&msg->LHN_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_LHN_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pathswitchrequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_PATHSWITCHREQUEST_STRUCT                       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->CSG_Id_present = false;
    msg->CellAccessMode_present = false;
    msg->SourceMME_GUMMEI_present = false;
    msg->CSGMembershipStatus_present = false;
    msg->Tunnel_Information_for_BBF_present = false;
    msg->LHN_ID_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PathSwitchRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDDLLIST == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobeswitcheddllist(ptr, &msg->E_RABToBeSwitchedDLList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_SOURCEMME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->SourceMME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_EUTRAN_CGI == ie_id) {
        if(liblte_s1ap_unpack_eutran_cgi(ptr, &msg->EUTRAN_CGI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TAI == ie_id) {
        if(liblte_s1ap_unpack_tai(ptr, &msg->TAI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UESECURITYCAPABILITIES == ie_id) {
        if(liblte_s1ap_unpack_uesecuritycapabilities(ptr, &msg->UESecurityCapabilities) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CSG_ID == ie_id) {
        if(liblte_s1ap_unpack_csg_id(ptr, &msg->CSG_Id) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSG_Id_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CELLACCESSMODE == ie_id) {
        if(liblte_s1ap_unpack_cellaccessmode(ptr, &msg->CellAccessMode) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CellAccessMode_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SOURCEMME_GUMMEI == ie_id) {
        if(liblte_s1ap_unpack_gummei(ptr, &msg->SourceMME_GUMMEI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SourceMME_GUMMEI_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS == ie_id) {
        if(liblte_s1ap_unpack_csgmembershipstatus(ptr, &msg->CSGMembershipStatus) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSGMembershipStatus_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_TUNNEL_INFORMATION_FOR_BBF == ie_id) {
        if(liblte_s1ap_unpack_tunnelinformation(ptr, &msg->Tunnel_Information_for_BBF) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->Tunnel_Information_for_BBF_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_LHN_ID == ie_id) {
        if(liblte_s1ap_unpack_lhn_id(ptr, &msg->LHN_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->LHN_ID_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message PathSwitchRequestAcknowledge STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_pathswitchrequestacknowledge(
  LIBLTE_S1AP_MESSAGE_PATHSWITCHREQUESTACKNOWLEDGE_STRUCT            *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PathSwitchRequestAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 9;
    if(!msg->uEaggregateMaximumBitrate_present)
      n_ie--;
    if(!msg->E_RABToBeSwitchedULList_present)
      n_ie--;
    if(!msg->E_RABToBeReleasedList_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    if(!msg->MME_UE_S1AP_ID_2_present)
      n_ie--;
    if(!msg->CSGMembershipStatus_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - uEaggregateMaximumBitrate
    if(msg->uEaggregateMaximumBitrate_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABToBeSwitchedULList
    if(msg->E_RABToBeSwitchedULList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabtobeswitchedullist(&msg->E_RABToBeSwitchedULList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDULLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABToBeReleasedList
    if(msg->E_RABToBeReleasedList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rablist(&msg->E_RABToBeReleasedList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABTOBERELEASEDLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SecurityContext
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_securitycontext(&msg->SecurityContext, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SECURITYCONTEXT,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - MME_UE_S1AP_ID_2
    if(msg->MME_UE_S1AP_ID_2_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID_2, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID_2,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSGMembershipStatus
    if(msg->CSGMembershipStatus_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_pathswitchrequestacknowledge(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_PATHSWITCHREQUESTACKNOWLEDGE_STRUCT            *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->uEaggregateMaximumBitrate_present = false;
    msg->E_RABToBeSwitchedULList_present = false;
    msg->E_RABToBeReleasedList_present = false;
    msg->CriticalityDiagnostics_present = false;
    msg->MME_UE_S1AP_ID_2_present = false;
    msg->CSGMembershipStatus_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PathSwitchRequestAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE == ie_id) {
        if(liblte_s1ap_unpack_ueaggregatemaximumbitrate(ptr, &msg->uEaggregateMaximumBitrate) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->uEaggregateMaximumBitrate_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_E_RABTOBESWITCHEDULLIST == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobeswitchedullist(ptr, &msg->E_RABToBeSwitchedULList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABToBeSwitchedULList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_E_RABTOBERELEASEDLIST == ie_id) {
        if(liblte_s1ap_unpack_e_rablist(ptr, &msg->E_RABToBeReleasedList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABToBeReleasedList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SECURITYCONTEXT == ie_id) {
        if(liblte_s1ap_unpack_securitycontext(ptr, &msg->SecurityContext) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID_2 == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID_2) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MME_UE_S1AP_ID_2_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS == ie_id) {
        if(liblte_s1ap_unpack_csgmembershipstatus(ptr, &msg->CSGMembershipStatus) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSGMembershipStatus_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABSetupRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetuprequest(
  LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT                       *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->uEaggregateMaximumBitrate_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - uEaggregateMaximumBitrate
    if(msg->uEaggregateMaximumBitrate_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABToBeSetupListBearerSUReq
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobesetuplistbearersureq(&msg->E_RABToBeSetupListBearerSUReq, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBESETUPLISTBEARERSUREQ,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetuprequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT                       *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->uEaggregateMaximumBitrate_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE == ie_id) {
        if(liblte_s1ap_unpack_ueaggregatemaximumbitrate(ptr, &msg->uEaggregateMaximumBitrate) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->uEaggregateMaximumBitrate_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_E_RABTOBESETUPLISTBEARERSUREQ == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobesetuplistbearersureq(ptr, &msg->E_RABToBeSetupListBearerSUReq) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABSetupResponse STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabsetupresponse(
  LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT                      *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 5;
    if(!msg->E_RABSetupListBearerSURes_present)
      n_ie--;
    if(!msg->E_RABFailedToSetupListBearerSURes_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABSetupListBearerSURes
    if(msg->E_RABSetupListBearerSURes_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabsetuplistbearersures(&msg->E_RABSetupListBearerSURes, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABSETUPLISTBEARERSURES,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABFailedToSetupListBearerSURes
    if(msg->E_RABFailedToSetupListBearerSURes_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToSetupListBearerSURes, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPLISTBEARERSURES,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabsetupresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT                      *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->E_RABSetupListBearerSURes_present = false;
    msg->E_RABFailedToSetupListBearerSURes_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABSetupResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABSETUPLISTBEARERSURES == ie_id) {
        if(liblte_s1ap_unpack_e_rabsetuplistbearersures(ptr, &msg->E_RABSetupListBearerSURes) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABSetupListBearerSURes_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPLISTBEARERSURES == ie_id) {
        if(liblte_s1ap_unpack_e_rablist(ptr, &msg->E_RABFailedToSetupListBearerSURes) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABFailedToSetupListBearerSURes_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABModifyRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyrequest(
  LIBLTE_S1AP_MESSAGE_E_RABMODIFYREQUEST_STRUCT                      *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABModifyRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 4;
    if(!msg->uEaggregateMaximumBitrate_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - uEaggregateMaximumBitrate
    if(msg->uEaggregateMaximumBitrate_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABToBeModifiedListBearerModReq
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobemodifiedlistbearermodreq(&msg->E_RABToBeModifiedListBearerModReq, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBEMODIFIEDLISTBEARERMODREQ,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabmodifyrequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABMODIFYREQUEST_STRUCT                      *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->uEaggregateMaximumBitrate_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABModifyRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE == ie_id) {
        if(liblte_s1ap_unpack_ueaggregatemaximumbitrate(ptr, &msg->uEaggregateMaximumBitrate) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->uEaggregateMaximumBitrate_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_E_RABTOBEMODIFIEDLISTBEARERMODREQ == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobemodifiedlistbearermodreq(ptr, &msg->E_RABToBeModifiedListBearerModReq) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABModifyResponse STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabmodifyresponse(
  LIBLTE_S1AP_MESSAGE_E_RABMODIFYRESPONSE_STRUCT                     *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABModifyResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 5;
    if(!msg->E_RABModifyListBearerModRes_present)
      n_ie--;
    if(!msg->E_RABFailedToModifyList_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABModifyListBearerModRes
    if(msg->E_RABModifyListBearerModRes_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabmodifylistbearermodres(&msg->E_RABModifyListBearerModRes, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABMODIFYLISTBEARERMODRES,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABFailedToModifyList
    if(msg->E_RABFailedToModifyList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToModifyList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABFAILEDTOMODIFYLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabmodifyresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABMODIFYRESPONSE_STRUCT                     *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->E_RABModifyListBearerModRes_present = false;
    msg->E_RABFailedToModifyList_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABModifyResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABMODIFYLISTBEARERMODRES == ie_id) {
        if(liblte_s1ap_unpack_e_rabmodifylistbearermodres(ptr, &msg->E_RABModifyListBearerModRes) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABModifyListBearerModRes_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_E_RABFAILEDTOMODIFYLIST == ie_id) {
        if(liblte_s1ap_unpack_e_rablist(ptr, &msg->E_RABFailedToModifyList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABFailedToModifyList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message E_RABReleaseResponse STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_e_rabreleaseresponse(
  LIBLTE_S1AP_MESSAGE_E_RABRELEASERESPONSE_STRUCT                    *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 6;
    if(!msg->E_RABReleaseListBearerRelComp_present)
      n_ie--;
    if(!msg->E_RABFailedToReleaseList_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    if(!msg->UserLocationInformation_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABReleaseListBearerRelComp
    if(msg->E_RABReleaseListBearerRelComp_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabreleaselistbearerrelcomp(&msg->E_RABReleaseListBearerRelComp, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABRELEASELISTBEARERRELCOMP,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - E_RABFailedToReleaseList
    if(msg->E_RABFailedToReleaseList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToReleaseList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABFAILEDTORELEASELIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - UserLocationInformation
    if(msg->UserLocationInformation_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_userlocationinformation(&msg->UserLocationInformation, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_USERLOCATIONINFORMATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_e_rabreleaseresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_E_RABRELEASERESPONSE_STRUCT                    *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->E_RABReleaseListBearerRelComp_present = false;
    msg->E_RABFailedToReleaseList_present = false;
    msg->CriticalityDiagnostics_present = false;
    msg->UserLocationInformation_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("E-RABReleaseResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABRELEASELISTBEARERRELCOMP == ie_id) {
        if(liblte_s1ap_unpack_e_rabreleaselistbearerrelcomp(ptr, &msg->E_RABReleaseListBearerRelComp) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABReleaseListBearerRelComp_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_E_RABFAILEDTORELEASELIST == ie_id) {
        if(liblte_s1ap_unpack_e_rablist(ptr, &msg->E_RABFailedToReleaseList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABFailedToReleaseList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_USERLOCATIONINFORMATION == ie_id) {
        if(liblte_s1ap_unpack_userlocationinformation(ptr, &msg->UserLocationInformation) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->UserLocationInformation_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message InitialContextSetupRequest STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetuprequest(
  LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("InitialContextSetupRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 19;
    if(!msg->TraceActivation_present)
      n_ie--;
    if(!msg->HandoverRestrictionList_present)
      n_ie--;
    if(!msg->UERadioCapability_present)
      n_ie--;
    if(!msg->SubscriberProfileIDforRFP_present)
      n_ie--;
    if(!msg->CSFallbackIndicator_present)
      n_ie--;
    if(!msg->SRVCCOperationPossible_present)
      n_ie--;
    if(!msg->CSGMembershipStatus_present)
      n_ie--;
    if(!msg->RegisteredLAI_present)
      n_ie--;
    if(!msg->GUMMEI_ID_present)
      n_ie--;
    if(!msg->MME_UE_S1AP_ID_2_present)
      n_ie--;
    if(!msg->ManagementBasedMDTAllowed_present)
      n_ie--;
    if(!msg->ManagementBasedMDTPLMNList_present)
      n_ie--;
    if(!msg->AdditionalCSFallbackIndicator_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - uEaggregateMaximumBitrate
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_ueaggregatemaximumbitrate(&msg->uEaggregateMaximumBitrate, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABToBeSetupListCtxtSUReq
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabtobesetuplistctxtsureq(&msg->E_RABToBeSetupListCtxtSUReq, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABTOBESETUPLISTCTXTSUREQ,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - UESecurityCapabilities
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_uesecuritycapabilities(&msg->UESecurityCapabilities, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UESECURITYCAPABILITIES,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - SecurityKey
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_securitykey(&msg->SecurityKey, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_SECURITYKEY,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TraceActivation
    if(msg->TraceActivation_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_traceactivation(&msg->TraceActivation, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_TRACEACTIVATION,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - HandoverRestrictionList
    if(msg->HandoverRestrictionList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_handoverrestrictionlist(&msg->HandoverRestrictionList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_HANDOVERRESTRICTIONLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - UERadioCapability
    if(msg->UERadioCapability_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_ueradiocapability(&msg->UERadioCapability, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_UERADIOCAPABILITY,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SubscriberProfileIDforRFP
    if(msg->SubscriberProfileIDforRFP_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_subscriberprofileidforrfp(&msg->SubscriberProfileIDforRFP, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SUBSCRIBERPROFILEIDFORRFP,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSFallbackIndicator
    if(msg->CSFallbackIndicator_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csfallbackindicator(&msg->CSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSFALLBACKINDICATOR,
                                            LIBLTE_S1AP_CRITICALITY_REJECT,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - SRVCCOperationPossible
    if(msg->SRVCCOperationPossible_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_srvccoperationpossible(&msg->SRVCCOperationPossible, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_SRVCCOPERATIONPOSSIBLE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CSGMembershipStatus
    if(msg->CSGMembershipStatus_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csgmembershipstatus(&msg->CSGMembershipStatus, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - RegisteredLAI
    if(msg->RegisteredLAI_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_lai(&msg->RegisteredLAI, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_REGISTEREDLAI,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - GUMMEI_ID
    if(msg->GUMMEI_ID_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_gummei(&msg->GUMMEI_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_GUMMEI_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - MME_UE_S1AP_ID_2
    if(msg->MME_UE_S1AP_ID_2_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID_2, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID_2,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - ManagementBasedMDTAllowed
    if(msg->ManagementBasedMDTAllowed_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_managementbasedmdtallowed(&msg->ManagementBasedMDTAllowed, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MANAGEMENTBASEDMDTALLOWED,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - ManagementBasedMDTPLMNList
    if(msg->ManagementBasedMDTPLMNList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_mdtplmnlist(&msg->ManagementBasedMDTPLMNList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_MANAGEMENTBASEDMDTPLMNLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - AdditionalCSFallbackIndicator
    if(msg->AdditionalCSFallbackIndicator_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_additionalcsfallbackindicator(&msg->AdditionalCSFallbackIndicator, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_ADDITIONALCSFALLBACKINDICATOR,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_initialcontextsetuprequest(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->TraceActivation_present = false;
    msg->HandoverRestrictionList_present = false;
    msg->UERadioCapability_present = false;
    msg->SubscriberProfileIDforRFP_present = false;
    msg->CSFallbackIndicator_present = false;
    msg->SRVCCOperationPossible_present = false;
    msg->CSGMembershipStatus_present = false;
    msg->RegisteredLAI_present = false;
    msg->GUMMEI_ID_present = false;
    msg->MME_UE_S1AP_ID_2_present = false;
    msg->ManagementBasedMDTAllowed_present = false;
    msg->ManagementBasedMDTPLMNList_present = false;
    msg->AdditionalCSFallbackIndicator_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("InitialContextSetupRequestIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UEAGGREGATEMAXIMUMBITRATE == ie_id) {
        if(liblte_s1ap_unpack_ueaggregatemaximumbitrate(ptr, &msg->uEaggregateMaximumBitrate) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABTOBESETUPLISTCTXTSUREQ == ie_id) {
        if(liblte_s1ap_unpack_e_rabtobesetuplistctxtsureq(ptr, &msg->E_RABToBeSetupListCtxtSUReq) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UESECURITYCAPABILITIES == ie_id) {
        if(liblte_s1ap_unpack_uesecuritycapabilities(ptr, &msg->UESecurityCapabilities) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_SECURITYKEY == ie_id) {
        if(liblte_s1ap_unpack_securitykey(ptr, &msg->SecurityKey) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TRACEACTIVATION == ie_id) {
        if(liblte_s1ap_unpack_traceactivation(ptr, &msg->TraceActivation) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->TraceActivation_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_HANDOVERRESTRICTIONLIST == ie_id) {
        if(liblte_s1ap_unpack_handoverrestrictionlist(ptr, &msg->HandoverRestrictionList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->HandoverRestrictionList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_UERADIOCAPABILITY == ie_id) {
        if(liblte_s1ap_unpack_ueradiocapability(ptr, &msg->UERadioCapability) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->UERadioCapability_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SUBSCRIBERPROFILEIDFORRFP == ie_id) {
        if(liblte_s1ap_unpack_subscriberprofileidforrfp(ptr, &msg->SubscriberProfileIDforRFP) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SubscriberProfileIDforRFP_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CSFALLBACKINDICATOR == ie_id) {
        if(liblte_s1ap_unpack_csfallbackindicator(ptr, &msg->CSFallbackIndicator) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSFallbackIndicator_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_SRVCCOPERATIONPOSSIBLE == ie_id) {
        if(liblte_s1ap_unpack_srvccoperationpossible(ptr, &msg->SRVCCOperationPossible) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->SRVCCOperationPossible_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CSGMEMBERSHIPSTATUS == ie_id) {
        if(liblte_s1ap_unpack_csgmembershipstatus(ptr, &msg->CSGMembershipStatus) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSGMembershipStatus_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_REGISTEREDLAI == ie_id) {
        if(liblte_s1ap_unpack_lai(ptr, &msg->RegisteredLAI) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->RegisteredLAI_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_GUMMEI_ID == ie_id) {
        if(liblte_s1ap_unpack_gummei(ptr, &msg->GUMMEI_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->GUMMEI_ID_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID_2 == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID_2) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->MME_UE_S1AP_ID_2_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_MANAGEMENTBASEDMDTALLOWED == ie_id) {
        if(liblte_s1ap_unpack_managementbasedmdtallowed(ptr, &msg->ManagementBasedMDTAllowed) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->ManagementBasedMDTAllowed_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_MANAGEMENTBASEDMDTPLMNLIST == ie_id) {
        if(liblte_s1ap_unpack_mdtplmnlist(ptr, &msg->ManagementBasedMDTPLMNList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->ManagementBasedMDTPLMNList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_ADDITIONALCSFALLBACKINDICATOR == ie_id) {
        if(liblte_s1ap_unpack_additionalcsfallbackindicator(ptr, &msg->AdditionalCSFallbackIndicator) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message InitialContextSetupResponse STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_initialcontextsetupresponse(
  LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT             *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("InitialContextSetupResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 5;
    if(!msg->E_RABFailedToSetupListCtxtSURes_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABSetupListCtxtSURes
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabsetuplistctxtsures(&msg->E_RABSetupListCtxtSURes, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABSETUPLISTCTXTSURES,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABFailedToSetupListCtxtSURes
    if(msg->E_RABFailedToSetupListCtxtSURes_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rablist(&msg->E_RABFailedToSetupListCtxtSURes, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPLISTCTXTSURES,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_initialcontextsetupresponse(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT             *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->E_RABFailedToSetupListCtxtSURes_present = false;
    msg->CriticalityDiagnostics_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("InitialContextSetupResponseIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABSETUPLISTCTXTSURES == ie_id) {
        if(liblte_s1ap_unpack_e_rabsetuplistctxtsures(ptr, &msg->E_RABSetupListCtxtSURes) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPLISTCTXTSURES == ie_id) {
        if(liblte_s1ap_unpack_e_rablist(ptr, &msg->E_RABFailedToSetupListCtxtSURes) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABFailedToSetupListCtxtSURes_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message Paging STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_paging(
  LIBLTE_S1AP_MESSAGE_PAGING_STRUCT                                  *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PagingIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 7;
    if(!msg->pagingDRX_present)
      n_ie--;
    if(!msg->CSG_IdList_present)
      n_ie--;
    if(!msg->PagingPriority_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - UEIdentityIndexValue
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_ueidentityindexvalue(&msg->UEIdentityIndexValue, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UEIDENTITYINDEXVALUE,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - UEPagingID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_uepagingid(&msg->UEPagingID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_UEPAGINGID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - pagingDRX
    if(msg->pagingDRX_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_pagingdrx(&msg->pagingDRX, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_PAGINGDRX,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CNDomain
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_cndomain(&msg->CNDomain, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_CNDOMAIN,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - TAIList
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_tailist(&msg->TAIList, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TAILIST,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CSG_IdList
    if(msg->CSG_IdList_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csg_idlist(&msg->CSG_IdList, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSG_IDLIST,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - PagingPriority
    if(msg->PagingPriority_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_pagingpriority(&msg->PagingPriority, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_PAGINGPRIORITY,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_paging(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_PAGING_STRUCT                                  *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->pagingDRX_present = false;
    msg->CSG_IdList_present = false;
    msg->PagingPriority_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("PagingIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_UEIDENTITYINDEXVALUE == ie_id) {
        if(liblte_s1ap_unpack_ueidentityindexvalue(ptr, &msg->UEIdentityIndexValue) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_UEPAGINGID == ie_id) {
        if(liblte_s1ap_unpack_uepagingid(ptr, &msg->UEPagingID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_PAGINGDRX == ie_id) {
        if(liblte_s1ap_unpack_pagingdrx(ptr, &msg->pagingDRX) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->pagingDRX_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CNDOMAIN == ie_id) {
        if(liblte_s1ap_unpack_cndomain(ptr, &msg->CNDomain) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_TAILIST == ie_id) {
        if(liblte_s1ap_unpack_tailist(ptr, &msg->TAIList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CSG_IDLIST == ie_id) {
        if(liblte_s1ap_unpack_csg_idlist(ptr, &msg->CSG_IdList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSG_IdList_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_PAGINGPRIORITY == ie_id) {
        if(liblte_s1ap_unpack_pagingpriority(ptr, &msg->PagingPriority) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->PagingPriority_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* Protocol Message HandoverRequestAcknowledge STRUCT
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_handoverrequestacknowledge(
  LIBLTE_S1AP_MESSAGE_HANDOVERREQUESTACKNOWLEDGE_STRUCT              *msg,
  uint8_t                                                           **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {

    // Extension
    liblte_value_2_bits(msg->ext?1:0, ptr, 1);
    liblte_align_up_zero(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverRequestAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_ENCODE_FAIL;
    }

    // No. of ProtocolIE
    uint32_t n_ie = 8;
    if(!msg->E_RABFailedToSetupListHOReqAck_present)
      n_ie--;
    if(!msg->CSG_Id_present)
      n_ie--;
    if(!msg->CriticalityDiagnostics_present)
      n_ie--;
    if(!msg->CellAccessMode_present)
      n_ie--;
    liblte_value_2_bits(n_ie, ptr, 16);

    // Temp container for IEs
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t              *tmp_ptr;

    // ProtocolIE - MME_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_mme_ue_s1ap_id(&msg->MME_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - eNB_UE_S1AP_ID
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_enb_ue_s1ap_id(&msg->eNB_UE_S1AP_ID, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABAdmittedList
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_e_rabadmittedlist(&msg->E_RABAdmittedList, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_E_RABADMITTEDLIST,
                                          LIBLTE_S1AP_CRITICALITY_IGNORE,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - E_RABFailedToSetupListHOReqAck
    if(msg->E_RABFailedToSetupListHOReqAck_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_e_rabfailedtosetuplisthoreqack(&msg->E_RABFailedToSetupListHOReqAck, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPLISTHOREQACK,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - Target_ToSource_TransparentContainer
    
    tmp_ptr = tmp_msg.msg;
    if(liblte_s1ap_pack_target_tosource_transparentcontainer(&msg->Target_ToSource_TransparentContainer, &tmp_ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    liblte_align_up_zero(&tmp_ptr, 8);
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
    if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                          LIBLTE_S1AP_IE_ID_TARGET_TOSOURCE_TRANSPARENTCONTAINER,
                                          LIBLTE_S1AP_CRITICALITY_REJECT,
                                          ptr) != LIBLTE_SUCCESS) {
      return LIBLTE_ERROR_ENCODE_FAIL;
    }
    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    // ProtocolIE - CSG_Id
    if(msg->CSG_Id_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_csg_id(&msg->CSG_Id, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CSG_ID,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CriticalityDiagnostics
    if(msg->CriticalityDiagnostics_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    // ProtocolIE - CellAccessMode
    if(msg->CellAccessMode_present) {
      
      tmp_ptr = tmp_msg.msg;
      if(liblte_s1ap_pack_cellaccessmode(&msg->CellAccessMode, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      liblte_align_up_zero(&tmp_ptr, 8);
      tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;
      if(liblte_s1ap_pack_protocolie_header(tmp_msg.N_bits / 8,
                                            LIBLTE_S1AP_IE_ID_CELLACCESSMODE,
                                            LIBLTE_S1AP_CRITICALITY_IGNORE,
                                            ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
      memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
      *ptr += tmp_msg.N_bits;
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_handoverrequestacknowledge(
  uint8_t                                                           **ptr,
  LIBLTE_S1AP_MESSAGE_HANDOVERREQUESTACKNOWLEDGE_STRUCT              *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg != NULL &&
     ptr != NULL)
  {
    LIBLTE_S1AP_CRITICALITY_ENUM crit;
    uint32_t ie_id;
    uint32_t len;
    uint32_t n_ie;
    uint32_t i;

    // Set booleans
    msg->E_RABFailedToSetupListHOReqAck_present = false;
    msg->CSG_Id_present = false;
    msg->CriticalityDiagnostics_present = false;
    msg->CellAccessMode_present = false;

    // Extension
    msg->ext  = liblte_bits_2_value(ptr, 1);
    liblte_align_up(ptr, 8);
    if(msg->ext) {
      liblte_log_print("HandoverRequestAcknowledgeIEs error: S1AP ASN extensions not currently supported\n");
      return LIBLTE_ERROR_DECODE_FAIL;
    }

    // No. of ProtocolIE-Container
    n_ie = liblte_bits_2_value(ptr, 16);

    // Unpack ProtocolIE Fields
    for(i=0;i<n_ie;i++) {
      if(liblte_s1ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
      if(LIBLTE_S1AP_IE_ID_MME_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_mme_ue_s1ap_id(ptr, &msg->MME_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_ENB_UE_S1AP_ID == ie_id) {
        if(liblte_s1ap_unpack_enb_ue_s1ap_id(ptr, &msg->eNB_UE_S1AP_ID) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABADMITTEDLIST == ie_id) {
        if(liblte_s1ap_unpack_e_rabadmittedlist(ptr, &msg->E_RABAdmittedList) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_E_RABFAILEDTOSETUPLISTHOREQACK == ie_id) {
        if(liblte_s1ap_unpack_e_rabfailedtosetuplisthoreqack(ptr, &msg->E_RABFailedToSetupListHOReqAck) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->E_RABFailedToSetupListHOReqAck_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_TARGET_TOSOURCE_TRANSPARENTCONTAINER == ie_id) {
        if(liblte_s1ap_unpack_target_tosource_transparentcontainer(ptr, &msg->Target_ToSource_TransparentContainer) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
      } else      if(LIBLTE_S1AP_IE_ID_CSG_ID == ie_id) {
        if(liblte_s1ap_unpack_csg_id(ptr, &msg->CSG_Id) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CSG_Id_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) {
        if(liblte_s1ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CriticalityDiagnostics_present = true;
      } else      if(LIBLTE_S1AP_IE_ID_CELLACCESSMODE == ie_id) {
        if(liblte_s1ap_unpack_cellaccessmode(ptr, &msg->CellAccessMode) != LIBLTE_SUCCESS) {
          return LIBLTE_ERROR_DECODE_FAIL;
        }
        liblte_align_up(ptr, 8);
        msg->CellAccessMode_present = true;
      } 
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* ProtocolIE-Field
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolie_header(
  uint32_t                      len,
  uint32_t                      ie_id,
  LIBLTE_S1AP_CRITICALITY_ENUM  crit,
  uint8_t                     **ptr)
{
  liblte_value_2_bits(ie_id, ptr, 16); // ProtocolIE-ID
  liblte_value_2_bits(crit,  ptr, 2);  // Criticality
  liblte_align_up_zero(ptr, 8);
  if(len < 128) {                      // Length
    liblte_value_2_bits(0,   ptr, 1);
    liblte_value_2_bits(len, ptr, 7);
  } else if(len < 16383) {
    liblte_value_2_bits(1,   ptr, 1);
    liblte_value_2_bits(0,   ptr, 1);
    liblte_value_2_bits(len, ptr, 14);
  } else {
    // FIXME: Unlikely to have more than 16K of octets
  }

  return LIBLTE_SUCCESS;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolie_header(
  uint8_t                     **ptr,
  uint32_t                     *ie_id,
  LIBLTE_S1AP_CRITICALITY_ENUM *crit,
  uint32_t                     *len)
{
  *ie_id = liblte_bits_2_value(ptr, 16);                               // ProtocolIE-ID
  *crit  = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);  // Criticality
  liblte_align_up(ptr, 8);
  if(0 == liblte_bits_2_value(ptr, 1)) {                               // Length
    *len = liblte_bits_2_value(ptr, 7);
  } else {
    if(0 == liblte_bits_2_value(ptr, 1)) {
      *len = liblte_bits_2_value(ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }
  }

  return LIBLTE_SUCCESS;
}

/*******************************************************************************
/* InitiatingMessage CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_initiatingmessage(
  LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg,
  uint8_t                             **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg                                      != NULL &&
     ptr                                      != NULL)
  { 
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t *tmp_ptr = tmp_msg.msg;

    // Message
    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_LOCATIONREPORTINGCONTROL) {
      if(liblte_s1ap_pack_locationreportingcontrol(&msg->choice.LocationReportingControl, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKS1CDMA2000TUNNELING) {
      if(liblte_s1ap_pack_downlinks1cdma2000tunneling(&msg->choice.DownlinkS1cdma2000tunneling, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST) {
      if(liblte_s1ap_pack_s1setuprequest(&msg->choice.S1SetupRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECAPABILITYINFOINDICATION) {
      if(liblte_s1ap_pack_uecapabilityinfoindication(&msg->choice.UECapabilityInfoIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_LOCATIONREPORT) {
      if(liblte_s1ap_pack_locationreport(&msg->choice.LocationReport, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNONUEASSOCIATEDLPPATRANSPORT) {
      if(liblte_s1ap_pack_uplinknonueassociatedlppatransport(&msg->choice.UplinkNonUEAssociatedLPPaTransport, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKS1CDMA2000TUNNELING) {
      if(liblte_s1ap_pack_uplinks1cdma2000tunneling(&msg->choice.UplinkS1cdma2000tunneling, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_MMECONFIGURATIONTRANSFER) {
      if(liblte_s1ap_pack_mmeconfigurationtransfer(&msg->choice.MMEConfigurationTransfer, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_TRACESTART) {
      if(liblte_s1ap_pack_tracestart(&msg->choice.TraceStart, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_HANDOVERCANCEL) {
      if(liblte_s1ap_pack_handovercancel(&msg->choice.HandoverCancel, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UERADIOCAPABILITYMATCHREQUEST) {
      if(liblte_s1ap_pack_ueradiocapabilitymatchrequest(&msg->choice.UERadioCapabilityMatchRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT) {
      if(liblte_s1ap_pack_downlinknastransport(&msg->choice.DownlinkNASTransport, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALCONTEXTSETUPREQUEST) {
      if(liblte_s1ap_pack_initialcontextsetuprequest(&msg->choice.InitialContextSetupRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_HANDOVERREQUIRED) {
      if(liblte_s1ap_pack_handoverrequired(&msg->choice.HandoverRequired, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_MMEDIRECTINFORMATIONTRANSFER) {
      if(liblte_s1ap_pack_mmedirectinformationtransfer(&msg->choice.MMEDirectInformationTransfer, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_TRACEFAILUREINDICATION) {
      if(liblte_s1ap_pack_tracefailureindication(&msg->choice.TraceFailureIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_MMECONFIGURATIONUPDATE) {
      if(liblte_s1ap_pack_mmeconfigurationupdate(&msg->choice.MMEConfigurationUpdate, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_WRITEREPLACEWARNINGREQUEST) {
      if(liblte_s1ap_pack_writereplacewarningrequest(&msg->choice.WriteReplaceWarningRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ENBDIRECTINFORMATIONTRANSFER) {
      if(liblte_s1ap_pack_enbdirectinformationtransfer(&msg->choice.ENBDirectInformationTransfer, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKUEASSOCIATEDLPPATRANSPORT) {
      if(liblte_s1ap_pack_downlinkueassociatedlppatransport(&msg->choice.DownlinkUEAssociatedLPPaTransport, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_E_RABRELEASECOMMAND) {
      if(liblte_s1ap_pack_e_rabreleasecommand(&msg->choice.E_RABReleaseCommand, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_NASNONDELIVERYINDICATION) {
      if(liblte_s1ap_pack_nasnondeliveryindication(&msg->choice.NASNonDeliveryIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ENBCONFIGURATIONUPDATE) {
      if(liblte_s1ap_pack_enbconfigurationupdate(&msg->choice.ENBConfigurationUpdate, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKUEASSOCIATEDLPPATRANSPORT) {
      if(liblte_s1ap_pack_uplinkueassociatedlppatransport(&msg->choice.UplinkUEAssociatedLPPaTransport, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE) {
      if(liblte_s1ap_pack_initialuemessage(&msg->choice.InitialUEMessage, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_E_RABMODIFYREQUEST) {
      if(liblte_s1ap_pack_e_rabmodifyrequest(&msg->choice.E_RABModifyRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTMODIFICATIONREQUEST) {
      if(liblte_s1ap_pack_uecontextmodificationrequest(&msg->choice.UEContextModificationRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_E_RABSETUPREQUEST) {
      if(liblte_s1ap_pack_e_rabsetuprequest(&msg->choice.E_RABSetupRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_RESET) {
      if(liblte_s1ap_pack_reset(&msg->choice.Reset, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_OVERLOADSTART) {
      if(liblte_s1ap_pack_overloadstart(&msg->choice.OverloadStart, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_E_RABRELEASEINDICATION) {
      if(liblte_s1ap_pack_e_rabreleaseindication(&msg->choice.E_RABReleaseIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_LOCATIONREPORTINGFAILUREINDICATION) {
      if(liblte_s1ap_pack_locationreportingfailureindication(&msg->choice.LocationReportingFailureIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DEACTIVATETRACE) {
      if(liblte_s1ap_pack_deactivatetrace(&msg->choice.DeactivateTrace, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PATHSWITCHREQUEST) {
      if(liblte_s1ap_pack_pathswitchrequest(&msg->choice.PathSwitchRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_HANDOVERREQUEST) {
      if(liblte_s1ap_pack_handoverrequest(&msg->choice.HandoverRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNONUEASSOCIATEDLPPATRANSPORT) {
      if(liblte_s1ap_pack_downlinknonueassociatedlppatransport(&msg->choice.DownlinkNonUEAssociatedLPPaTransport, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_OVERLOADSTOP) {
      if(liblte_s1ap_pack_overloadstop(&msg->choice.OverloadStop, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PAGING) {
      if(liblte_s1ap_pack_paging(&msg->choice.Paging, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_HANDOVERNOTIFY) {
      if(liblte_s1ap_pack_handovernotify(&msg->choice.HandoverNotify, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PWSRESTARTINDICATION) {
      if(liblte_s1ap_pack_pwsrestartindication(&msg->choice.PWSRestartIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST) {
      if(liblte_s1ap_pack_uecontextreleaserequest(&msg->choice.UEContextReleaseRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT) {
      if(liblte_s1ap_pack_uplinknastransport(&msg->choice.UplinkNASTransport, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ENBCONFIGURATIONTRANSFER) {
      if(liblte_s1ap_pack_enbconfigurationtransfer(&msg->choice.ENBConfigurationTransfer, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_MMESTATUSTRANSFER) {
      if(liblte_s1ap_pack_mmestatustransfer(&msg->choice.MMEStatusTransfer, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_CELLTRAFFICTRACE) {
      if(liblte_s1ap_pack_celltraffictrace(&msg->choice.CellTrafficTrace, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASECOMMAND) {
      if(liblte_s1ap_pack_uecontextreleasecommand(&msg->choice.UEContextReleaseCommand, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_KILLREQUEST) {
      if(liblte_s1ap_pack_killrequest(&msg->choice.KillRequest, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PRIVATEMESSAGE) {
      if(liblte_s1ap_pack_privatemessage(&msg->choice.PrivateMessage, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ENBSTATUSTRANSFER) {
      if(liblte_s1ap_pack_enbstatustransfer(&msg->choice.ENBStatusTransfer, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ERRORINDICATION) {
      if(liblte_s1ap_pack_errorindication(&msg->choice.ErrorIndication, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } 
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;

    // Procedure code
    liblte_value_2_bits(msg->procedureCode, ptr, 8);

    // Criticality
    LIBLTE_S1AP_CRITICALITY_ENUM crit = liblte_s1ap_procedure_criticality[msg->procedureCode];
    liblte_value_2_bits(crit, ptr, 2);
    liblte_align_up_zero(ptr, 8);

    // Length
    uint32_t len = (tmp_msg.N_bits + 7) / 8;
    if(len < 128) {
      liblte_value_2_bits(0,   ptr, 1);
      liblte_value_2_bits(len, ptr, 7);
    } else if(len < 16383) {
      liblte_value_2_bits(1,   ptr, 1);
      liblte_value_2_bits(0,   ptr, 1);
      liblte_value_2_bits(len, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }

    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_initiatingmessage(
  uint8_t                             **ptr,
  LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg)
{  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg                                      != NULL &&
     ptr                                      != NULL)
  {
    // Procedure code
    msg->procedureCode  = liblte_bits_2_value(ptr, 8);

    // Criticality
    msg->criticality    = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);

    // Length
    uint32_t len = 0;
    if(0 == liblte_bits_2_value(ptr, 1)) {
      len = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        len = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Message
    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_LOCATIONREPORTINGCONTROL) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_LOCATIONREPORTINGCONTROL;
      if(liblte_s1ap_unpack_locationreportingcontrol(ptr, &msg->choice.LocationReportingControl) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_DOWNLINKS1CDMA2000TUNNELING) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKS1CDMA2000TUNNELING;
      if(liblte_s1ap_unpack_downlinks1cdma2000tunneling(ptr, &msg->choice.DownlinkS1cdma2000tunneling) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_S1SETUP) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST;
      if(liblte_s1ap_unpack_s1setuprequest(ptr, &msg->choice.S1SetupRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UECAPABILITYINFOINDICATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECAPABILITYINFOINDICATION;
      if(liblte_s1ap_unpack_uecapabilityinfoindication(ptr, &msg->choice.UECapabilityInfoIndication) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_LOCATIONREPORT) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_LOCATIONREPORT;
      if(liblte_s1ap_unpack_locationreport(ptr, &msg->choice.LocationReport) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UPLINKNONUEASSOCIATEDLPPATRANSPORT) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNONUEASSOCIATEDLPPATRANSPORT;
      if(liblte_s1ap_unpack_uplinknonueassociatedlppatransport(ptr, &msg->choice.UplinkNonUEAssociatedLPPaTransport) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UPLINKS1CDMA2000TUNNELING) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKS1CDMA2000TUNNELING;
      if(liblte_s1ap_unpack_uplinks1cdma2000tunneling(ptr, &msg->choice.UplinkS1cdma2000tunneling) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_MMECONFIGURATIONTRANSFER) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_MMECONFIGURATIONTRANSFER;
      if(liblte_s1ap_unpack_mmeconfigurationtransfer(ptr, &msg->choice.MMEConfigurationTransfer) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_TRACESTART) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_TRACESTART;
      if(liblte_s1ap_unpack_tracestart(ptr, &msg->choice.TraceStart) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_HANDOVERCANCEL) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_HANDOVERCANCEL;
      if(liblte_s1ap_unpack_handovercancel(ptr, &msg->choice.HandoverCancel) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UERADIOCAPABILITYMATCH) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UERADIOCAPABILITYMATCHREQUEST;
      if(liblte_s1ap_unpack_ueradiocapabilitymatchrequest(ptr, &msg->choice.UERadioCapabilityMatchRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT;
      if(liblte_s1ap_unpack_downlinknastransport(ptr, &msg->choice.DownlinkNASTransport) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_INITIALCONTEXTSETUP) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALCONTEXTSETUPREQUEST;
      if(liblte_s1ap_unpack_initialcontextsetuprequest(ptr, &msg->choice.InitialContextSetupRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_HANDOVERPREPARATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_HANDOVERREQUIRED;
      if(liblte_s1ap_unpack_handoverrequired(ptr, &msg->choice.HandoverRequired) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_MMEDIRECTINFORMATIONTRANSFER) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_MMEDIRECTINFORMATIONTRANSFER;
      if(liblte_s1ap_unpack_mmedirectinformationtransfer(ptr, &msg->choice.MMEDirectInformationTransfer) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_TRACEFAILUREINDICATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_TRACEFAILUREINDICATION;
      if(liblte_s1ap_unpack_tracefailureindication(ptr, &msg->choice.TraceFailureIndication) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_MMECONFIGURATIONUPDATE) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_MMECONFIGURATIONUPDATE;
      if(liblte_s1ap_unpack_mmeconfigurationupdate(ptr, &msg->choice.MMEConfigurationUpdate) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_WRITEREPLACEWARNING) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_WRITEREPLACEWARNINGREQUEST;
      if(liblte_s1ap_unpack_writereplacewarningrequest(ptr, &msg->choice.WriteReplaceWarningRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_ENBDIRECTINFORMATIONTRANSFER) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ENBDIRECTINFORMATIONTRANSFER;
      if(liblte_s1ap_unpack_enbdirectinformationtransfer(ptr, &msg->choice.ENBDirectInformationTransfer) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_DOWNLINKUEASSOCIATEDLPPATRANSPORT) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKUEASSOCIATEDLPPATRANSPORT;
      if(liblte_s1ap_unpack_downlinkueassociatedlppatransport(ptr, &msg->choice.DownlinkUEAssociatedLPPaTransport) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_E_RABRELEASE) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_E_RABRELEASECOMMAND;
      if(liblte_s1ap_unpack_e_rabreleasecommand(ptr, &msg->choice.E_RABReleaseCommand) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_NASNONDELIVERYINDICATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_NASNONDELIVERYINDICATION;
      if(liblte_s1ap_unpack_nasnondeliveryindication(ptr, &msg->choice.NASNonDeliveryIndication) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_ENBCONFIGURATIONUPDATE) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ENBCONFIGURATIONUPDATE;
      if(liblte_s1ap_unpack_enbconfigurationupdate(ptr, &msg->choice.ENBConfigurationUpdate) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UPLINKUEASSOCIATEDLPPATRANSPORT) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKUEASSOCIATEDLPPATRANSPORT;
      if(liblte_s1ap_unpack_uplinkueassociatedlppatransport(ptr, &msg->choice.UplinkUEAssociatedLPPaTransport) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_INITIALUEMESSAGE) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE;
      if(liblte_s1ap_unpack_initialuemessage(ptr, &msg->choice.InitialUEMessage) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_E_RABMODIFY) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_E_RABMODIFYREQUEST;
      if(liblte_s1ap_unpack_e_rabmodifyrequest(ptr, &msg->choice.E_RABModifyRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UECONTEXTMODIFICATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTMODIFICATIONREQUEST;
      if(liblte_s1ap_unpack_uecontextmodificationrequest(ptr, &msg->choice.UEContextModificationRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_E_RABSETUP) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_E_RABSETUPREQUEST;
      if(liblte_s1ap_unpack_e_rabsetuprequest(ptr, &msg->choice.E_RABSetupRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_RESET) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_RESET;
      if(liblte_s1ap_unpack_reset(ptr, &msg->choice.Reset) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_OVERLOADSTART) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_OVERLOADSTART;
      if(liblte_s1ap_unpack_overloadstart(ptr, &msg->choice.OverloadStart) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_E_RABRELEASEINDICATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_E_RABRELEASEINDICATION;
      if(liblte_s1ap_unpack_e_rabreleaseindication(ptr, &msg->choice.E_RABReleaseIndication) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_LOCATIONREPORTINGFAILUREINDICATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_LOCATIONREPORTINGFAILUREINDICATION;
      if(liblte_s1ap_unpack_locationreportingfailureindication(ptr, &msg->choice.LocationReportingFailureIndication) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_DEACTIVATETRACE) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DEACTIVATETRACE;
      if(liblte_s1ap_unpack_deactivatetrace(ptr, &msg->choice.DeactivateTrace) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_PATHSWITCHREQUEST) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PATHSWITCHREQUEST;
      if(liblte_s1ap_unpack_pathswitchrequest(ptr, &msg->choice.PathSwitchRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_HANDOVERRESOURCEALLOCATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_HANDOVERREQUEST;
      if(liblte_s1ap_unpack_handoverrequest(ptr, &msg->choice.HandoverRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_DOWNLINKNONUEASSOCIATEDLPPATRANSPORT) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNONUEASSOCIATEDLPPATRANSPORT;
      if(liblte_s1ap_unpack_downlinknonueassociatedlppatransport(ptr, &msg->choice.DownlinkNonUEAssociatedLPPaTransport) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_OVERLOADSTOP) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_OVERLOADSTOP;
      if(liblte_s1ap_unpack_overloadstop(ptr, &msg->choice.OverloadStop) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_PAGING) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PAGING;
      if(liblte_s1ap_unpack_paging(ptr, &msg->choice.Paging) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_HANDOVERNOTIFICATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_HANDOVERNOTIFY;
      if(liblte_s1ap_unpack_handovernotify(ptr, &msg->choice.HandoverNotify) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_PWSRESTARTINDICATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PWSRESTARTINDICATION;
      if(liblte_s1ap_unpack_pwsrestartindication(ptr, &msg->choice.PWSRestartIndication) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UECONTEXTRELEASEREQUEST) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST;
      if(liblte_s1ap_unpack_uecontextreleaserequest(ptr, &msg->choice.UEContextReleaseRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UPLINKNASTRANSPORT) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT;
      if(liblte_s1ap_unpack_uplinknastransport(ptr, &msg->choice.UplinkNASTransport) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_ENBCONFIGURATIONTRANSFER) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ENBCONFIGURATIONTRANSFER;
      if(liblte_s1ap_unpack_enbconfigurationtransfer(ptr, &msg->choice.ENBConfigurationTransfer) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_MMESTATUSTRANSFER) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_MMESTATUSTRANSFER;
      if(liblte_s1ap_unpack_mmestatustransfer(ptr, &msg->choice.MMEStatusTransfer) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_CELLTRAFFICTRACE) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_CELLTRAFFICTRACE;
      if(liblte_s1ap_unpack_celltraffictrace(ptr, &msg->choice.CellTrafficTrace) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UECONTEXTRELEASE) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASECOMMAND;
      if(liblte_s1ap_unpack_uecontextreleasecommand(ptr, &msg->choice.UEContextReleaseCommand) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_KILL) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_KILLREQUEST;
      if(liblte_s1ap_unpack_killrequest(ptr, &msg->choice.KillRequest) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_PRIVATEMESSAGE) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PRIVATEMESSAGE;
      if(liblte_s1ap_unpack_privatemessage(ptr, &msg->choice.PrivateMessage) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_ENBSTATUSTRANSFER) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ENBSTATUSTRANSFER;
      if(liblte_s1ap_unpack_enbstatustransfer(ptr, &msg->choice.ENBStatusTransfer) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_ERRORINDICATION) {
      msg->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_ERRORINDICATION;
      if(liblte_s1ap_unpack_errorindication(ptr, &msg->choice.ErrorIndication) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* UnsuccessfulOutcome CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_unsuccessfuloutcome(
  LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT *msg,
  uint8_t                               **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg                                      != NULL &&
     ptr                                      != NULL)
  { 
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t *tmp_ptr = tmp_msg.msg;

    // Message
    if(msg->choice_type == LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_S1SETUPFAILURE) {
      if(liblte_s1ap_pack_s1setupfailure(&msg->choice.S1SetupFailure, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_PATHSWITCHREQUESTFAILURE) {
      if(liblte_s1ap_pack_pathswitchrequestfailure(&msg->choice.PathSwitchRequestFailure, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_UECONTEXTMODIFICATIONFAILURE) {
      if(liblte_s1ap_pack_uecontextmodificationfailure(&msg->choice.UEContextModificationFailure, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPFAILURE) {
      if(liblte_s1ap_pack_initialcontextsetupfailure(&msg->choice.InitialContextSetupFailure, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_ENBCONFIGURATIONUPDATEFAILURE) {
      if(liblte_s1ap_pack_enbconfigurationupdatefailure(&msg->choice.ENBConfigurationUpdateFailure, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_HANDOVERPREPARATIONFAILURE) {
      if(liblte_s1ap_pack_handoverpreparationfailure(&msg->choice.HandoverPreparationFailure, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_HANDOVERFAILURE) {
      if(liblte_s1ap_pack_handoverfailure(&msg->choice.HandoverFailure, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_MMECONFIGURATIONUPDATEFAILURE) {
      if(liblte_s1ap_pack_mmeconfigurationupdatefailure(&msg->choice.MMEConfigurationUpdateFailure, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } 
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;

    // Procedure code
    liblte_value_2_bits(msg->procedureCode, ptr, 8);

    // Criticality
    LIBLTE_S1AP_CRITICALITY_ENUM crit = liblte_s1ap_procedure_criticality[msg->procedureCode];
    liblte_value_2_bits(crit, ptr, 2);
    liblte_align_up_zero(ptr, 8);

    // Length
    uint32_t len = (tmp_msg.N_bits + 7) / 8;
    if(len < 128) {
      liblte_value_2_bits(0,   ptr, 1);
      liblte_value_2_bits(len, ptr, 7);
    } else if(len < 16383) {
      liblte_value_2_bits(1,   ptr, 1);
      liblte_value_2_bits(0,   ptr, 1);
      liblte_value_2_bits(len, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }

    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_unsuccessfuloutcome(
  uint8_t                               **ptr,
  LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT *msg)
{  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg                                      != NULL &&
     ptr                                      != NULL)
  {
    // Procedure code
    msg->procedureCode  = liblte_bits_2_value(ptr, 8);

    // Criticality
    msg->criticality    = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);

    // Length
    uint32_t len = 0;
    if(0 == liblte_bits_2_value(ptr, 1)) {
      len = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        len = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Message
    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_S1SETUP) {
      msg->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_S1SETUPFAILURE;
      if(liblte_s1ap_unpack_s1setupfailure(ptr, &msg->choice.S1SetupFailure) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_PATHSWITCHREQUEST) {
      msg->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_PATHSWITCHREQUESTFAILURE;
      if(liblte_s1ap_unpack_pathswitchrequestfailure(ptr, &msg->choice.PathSwitchRequestFailure) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UECONTEXTMODIFICATION) {
      msg->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_UECONTEXTMODIFICATIONFAILURE;
      if(liblte_s1ap_unpack_uecontextmodificationfailure(ptr, &msg->choice.UEContextModificationFailure) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_INITIALCONTEXTSETUP) {
      msg->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPFAILURE;
      if(liblte_s1ap_unpack_initialcontextsetupfailure(ptr, &msg->choice.InitialContextSetupFailure) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_ENBCONFIGURATIONUPDATE) {
      msg->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_ENBCONFIGURATIONUPDATEFAILURE;
      if(liblte_s1ap_unpack_enbconfigurationupdatefailure(ptr, &msg->choice.ENBConfigurationUpdateFailure) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_HANDOVERPREPARATION) {
      msg->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_HANDOVERPREPARATIONFAILURE;
      if(liblte_s1ap_unpack_handoverpreparationfailure(ptr, &msg->choice.HandoverPreparationFailure) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_HANDOVERRESOURCEALLOCATION) {
      msg->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_HANDOVERFAILURE;
      if(liblte_s1ap_unpack_handoverfailure(ptr, &msg->choice.HandoverFailure) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_MMECONFIGURATIONUPDATE) {
      msg->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_MMECONFIGURATIONUPDATEFAILURE;
      if(liblte_s1ap_unpack_mmeconfigurationupdatefailure(ptr, &msg->choice.MMEConfigurationUpdateFailure) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}

/*******************************************************************************
/* SuccessfulOutcome CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_successfuloutcome(
  LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg,
  uint8_t                             **ptr)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg                                      != NULL &&
     ptr                                      != NULL)
  { 
    LIBLTE_BIT_MSG_STRUCT tmp_msg;
    uint8_t *tmp_ptr = tmp_msg.msg;

    // Message
    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_HANDOVERREQUESTACKNOWLEDGE) {
      if(liblte_s1ap_pack_handoverrequestacknowledge(&msg->choice.HandoverRequestAcknowledge, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UECONTEXTRELEASECOMPLETE) {
      if(liblte_s1ap_pack_uecontextreleasecomplete(&msg->choice.UEContextReleaseComplete, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UERADIOCAPABILITYMATCHRESPONSE) {
      if(liblte_s1ap_pack_ueradiocapabilitymatchresponse(&msg->choice.UERadioCapabilityMatchResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPRESPONSE) {
      if(liblte_s1ap_pack_initialcontextsetupresponse(&msg->choice.InitialContextSetupResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_E_RABSETUPRESPONSE) {
      if(liblte_s1ap_pack_e_rabsetupresponse(&msg->choice.E_RABSetupResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_PATHSWITCHREQUESTACKNOWLEDGE) {
      if(liblte_s1ap_pack_pathswitchrequestacknowledge(&msg->choice.PathSwitchRequestAcknowledge, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_MMECONFIGURATIONUPDATEACKNOWLEDGE) {
      if(liblte_s1ap_pack_mmeconfigurationupdateacknowledge(&msg->choice.MMEConfigurationUpdateAcknowledge, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_RESETACKNOWLEDGE) {
      if(liblte_s1ap_pack_resetacknowledge(&msg->choice.ResetAcknowledge, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_ENBCONFIGURATIONUPDATEACKNOWLEDGE) {
      if(liblte_s1ap_pack_enbconfigurationupdateacknowledge(&msg->choice.ENBConfigurationUpdateAcknowledge, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_E_RABMODIFYRESPONSE) {
      if(liblte_s1ap_pack_e_rabmodifyresponse(&msg->choice.E_RABModifyResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_WRITEREPLACEWARNINGRESPONSE) {
      if(liblte_s1ap_pack_writereplacewarningresponse(&msg->choice.WriteReplaceWarningResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE) {
      if(liblte_s1ap_pack_s1setupresponse(&msg->choice.S1SetupResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_KILLRESPONSE) {
      if(liblte_s1ap_pack_killresponse(&msg->choice.KillResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UECONTEXTMODIFICATIONRESPONSE) {
      if(liblte_s1ap_pack_uecontextmodificationresponse(&msg->choice.UEContextModificationResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_HANDOVERCOMMAND) {
      if(liblte_s1ap_pack_handovercommand(&msg->choice.HandoverCommand, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_HANDOVERCANCELACKNOWLEDGE) {
      if(liblte_s1ap_pack_handovercancelacknowledge(&msg->choice.HandoverCancelAcknowledge, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else    if(msg->choice_type == LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_E_RABRELEASERESPONSE) {
      if(liblte_s1ap_pack_e_rabreleaseresponse(&msg->choice.E_RABReleaseResponse, &tmp_ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } 
    tmp_msg.N_bits = tmp_ptr - tmp_msg.msg;

    // Procedure code
    liblte_value_2_bits(msg->procedureCode, ptr, 8);

    // Criticality
    LIBLTE_S1AP_CRITICALITY_ENUM crit = liblte_s1ap_procedure_criticality[msg->procedureCode];
    liblte_value_2_bits(crit, ptr, 2);
    liblte_align_up_zero(ptr, 8);

    // Length
    uint32_t len = (tmp_msg.N_bits + 7) / 8;
    if(len < 128) {
      liblte_value_2_bits(0,   ptr, 1);
      liblte_value_2_bits(len, ptr, 7);
    } else if(len < 16383) {
      liblte_value_2_bits(1,   ptr, 1);
      liblte_value_2_bits(0,   ptr, 1);
      liblte_value_2_bits(len, ptr, 14);
    } else {
      // FIXME: Unlikely to have more than 16K of octets
    }

    memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits);
    *ptr += tmp_msg.N_bits;

    err = LIBLTE_SUCCESS;
  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_successfuloutcome(
  uint8_t                             **ptr,
  LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg)
{  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;

  if(msg                                      != NULL &&
     ptr                                      != NULL)
  {
    // Procedure code
    msg->procedureCode  = liblte_bits_2_value(ptr, 8);

    // Criticality
    msg->criticality    = (LIBLTE_S1AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);

    // Length
    uint32_t len = 0;
    if(0 == liblte_bits_2_value(ptr, 1)) {
      len = liblte_bits_2_value(ptr, 7);
    } else {
      if(0 == liblte_bits_2_value(ptr, 1)) {
        len = liblte_bits_2_value(ptr, 14);
      } else {
        // FIXME: Unlikely to have more than 16K of octets
      }
    }

    // Message
    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_HANDOVERRESOURCEALLOCATION) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_HANDOVERREQUESTACKNOWLEDGE;
      if(liblte_s1ap_unpack_handoverrequestacknowledge(ptr, &msg->choice.HandoverRequestAcknowledge) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UECONTEXTRELEASE) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UECONTEXTRELEASECOMPLETE;
      if(liblte_s1ap_unpack_uecontextreleasecomplete(ptr, &msg->choice.UEContextReleaseComplete) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UERADIOCAPABILITYMATCH) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UERADIOCAPABILITYMATCHRESPONSE;
      if(liblte_s1ap_unpack_ueradiocapabilitymatchresponse(ptr, &msg->choice.UERadioCapabilityMatchResponse) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_INITIALCONTEXTSETUP) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPRESPONSE;
      if(liblte_s1ap_unpack_initialcontextsetupresponse(ptr, &msg->choice.InitialContextSetupResponse) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_E_RABSETUP) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_E_RABSETUPRESPONSE;
      if(liblte_s1ap_unpack_e_rabsetupresponse(ptr, &msg->choice.E_RABSetupResponse) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_PATHSWITCHREQUEST) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_PATHSWITCHREQUESTACKNOWLEDGE;
      if(liblte_s1ap_unpack_pathswitchrequestacknowledge(ptr, &msg->choice.PathSwitchRequestAcknowledge) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_MMECONFIGURATIONUPDATE) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_MMECONFIGURATIONUPDATEACKNOWLEDGE;
      if(liblte_s1ap_unpack_mmeconfigurationupdateacknowledge(ptr, &msg->choice.MMEConfigurationUpdateAcknowledge) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_RESET) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_RESETACKNOWLEDGE;
      if(liblte_s1ap_unpack_resetacknowledge(ptr, &msg->choice.ResetAcknowledge) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_ENBCONFIGURATIONUPDATE) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_ENBCONFIGURATIONUPDATEACKNOWLEDGE;
      if(liblte_s1ap_unpack_enbconfigurationupdateacknowledge(ptr, &msg->choice.ENBConfigurationUpdateAcknowledge) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_E_RABMODIFY) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_E_RABMODIFYRESPONSE;
      if(liblte_s1ap_unpack_e_rabmodifyresponse(ptr, &msg->choice.E_RABModifyResponse) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_WRITEREPLACEWARNING) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_WRITEREPLACEWARNINGRESPONSE;
      if(liblte_s1ap_unpack_writereplacewarningresponse(ptr, &msg->choice.WriteReplaceWarningResponse) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_S1SETUP) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE;
      if(liblte_s1ap_unpack_s1setupresponse(ptr, &msg->choice.S1SetupResponse) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_KILL) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_KILLRESPONSE;
      if(liblte_s1ap_unpack_killresponse(ptr, &msg->choice.KillResponse) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_UECONTEXTMODIFICATION) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UECONTEXTMODIFICATIONRESPONSE;
      if(liblte_s1ap_unpack_uecontextmodificationresponse(ptr, &msg->choice.UEContextModificationResponse) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_HANDOVERPREPARATION) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_HANDOVERCOMMAND;
      if(liblte_s1ap_unpack_handovercommand(ptr, &msg->choice.HandoverCommand) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_HANDOVERCANCEL) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_HANDOVERCANCELACKNOWLEDGE;
      if(liblte_s1ap_unpack_handovercancelacknowledge(ptr, &msg->choice.HandoverCancelAcknowledge) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } else    if(msg->procedureCode == LIBLTE_S1AP_PROC_ID_E_RABRELEASE) {
      msg->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_E_RABRELEASERESPONSE;
      if(liblte_s1ap_unpack_e_rabreleaseresponse(ptr, &msg->choice.E_RABReleaseResponse) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    } 
    err = LIBLTE_SUCCESS;
  }
  return err;
}


/*******************************************************************************
/* S1AP_PDU CHOICE
********************************************************************************/
LIBLTE_ERROR_ENUM liblte_s1ap_pack_s1ap_pdu(
  LIBLTE_S1AP_S1AP_PDU_STRUCT *s1ap_pdu,
  LIBLTE_BYTE_MSG_STRUCT      *msg)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
  LIBLTE_BIT_MSG_STRUCT bit_msg;

  if(s1ap_pdu                                 != NULL &&
     msg                                      != NULL)
  {
    uint8_t *p    = bit_msg.msg;
    uint8_t **ptr = &p;

    // Extension
    liblte_value_2_bits(s1ap_pdu->ext?1:0, ptr, 1);

    // Message choice
    liblte_value_2_bits(s1ap_pdu->choice_type, ptr, 2);
    liblte_align_up_zero(ptr, 8);

    // Message
    if(LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE == s1ap_pdu->choice_type) {
      if(liblte_s1ap_pack_initiatingmessage(&s1ap_pdu->choice.initiatingMessage, ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    } else if(LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME == s1ap_pdu->choice_type) {
      if(liblte_s1ap_pack_successfuloutcome(&s1ap_pdu->choice.successfulOutcome, ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
     }else if(LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME == s1ap_pdu->choice_type) {
      if(liblte_s1ap_pack_unsuccessfuloutcome(&s1ap_pdu->choice.unsuccessfulOutcome, ptr) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_ENCODE_FAIL;
      }
    }

    liblte_align_up_zero(ptr, 8);
    bit_msg.N_bits = (*ptr - bit_msg.msg);

    liblte_pack(&bit_msg, msg);
    err = LIBLTE_SUCCESS;

  }
  return err;
}

LIBLTE_ERROR_ENUM liblte_s1ap_unpack_s1ap_pdu(
  LIBLTE_BYTE_MSG_STRUCT      *msg,
  LIBLTE_S1AP_S1AP_PDU_STRUCT *s1ap_pdu)
{
  LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
  LIBLTE_BIT_MSG_STRUCT bit_msg;

  if(s1ap_pdu                                 != NULL &&
     msg                                      != NULL)
  {
    liblte_unpack(msg, &bit_msg);

    uint8_t *p    = bit_msg.msg;
    uint8_t **ptr = &p;

    // Extension
    s1ap_pdu->ext = liblte_bits_2_value(ptr, 1);

    // Message choice
    s1ap_pdu->choice_type = (LIBLTE_S1AP_S1AP_PDU_CHOICE_ENUM)liblte_bits_2_value(ptr, 2);
    liblte_align_up(ptr, 8);

    // Message
    if(LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE == s1ap_pdu->choice_type) {
      if(liblte_s1ap_unpack_initiatingmessage(ptr, &s1ap_pdu->choice.initiatingMessage) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }else if(LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME == s1ap_pdu->choice_type) {
      if(liblte_s1ap_unpack_successfuloutcome(ptr, &s1ap_pdu->choice.successfulOutcome) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }else if(LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME == s1ap_pdu->choice_type) {
      if(liblte_s1ap_unpack_unsuccessfuloutcome(ptr, &s1ap_pdu->choice.unsuccessfulOutcome) != LIBLTE_SUCCESS) {
        return LIBLTE_ERROR_DECODE_FAIL;
      }
    }

    err = LIBLTE_SUCCESS;
  }
  return err;
}
