int
encode_short_mac (
  ShortMac * shortmac,
  uint8_t iei,
  uint8_t * buffer,
  uint32_t len)
{
  uint32_t                                encoded = 0;

  /*
   * Checking IEI and pointer
   */
  CHECK_PDU_POINTER_AND_LENGTH_ENCODER (buffer, SHORT_MAC_MINIMUM_LENGTH, len);
#if NAS_DEBUG
  dump_short_mac_xml (shortmac, iei);
#endif

  if (iei > 0) {
    *buffer = iei;
    encoded++;
  }

  IES_ENCODE_U16 (buffer, encoded, *shortmac);
  return encoded;
}
int encode_location_area_identification(LocationAreaIdentification *locationareaidentification, uint8_t iei, uint8_t *buffer, uint32_t len)
{
    uint32_t encoded = 0;
    /* Checking IEI and pointer */
    CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, LOCATION_AREA_IDENTIFICATION_MINIMUM_LENGTH, len);
#if defined (NAS_DEBUG)
    dump_location_area_identification_xml(locationareaidentification, iei);
#endif
    if (iei > 0)
    {
        *buffer = iei;
        encoded++;
    }
    *(buffer + encoded) = 0x00 | ((locationareaidentification->mccdigit2 & 0xf) << 4) |
    (locationareaidentification->mccdigit1 & 0xf);
    encoded++;
    *(buffer + encoded) = 0x00 | ((locationareaidentification->mncdigit3 & 0xf) << 4) |
    (locationareaidentification->mccdigit3 & 0xf);
    encoded++;
    *(buffer + encoded) = 0x00 | ((locationareaidentification->mncdigit2 & 0xf) << 4) |
    (locationareaidentification->mncdigit1 & 0xf);
    encoded++;
    IES_ENCODE_U16(buffer, encoded, locationareaidentification->lac);
    return encoded;
}
int encode_tracking_area_identity_list(TrackingAreaIdentityList *trackingareaidentitylist, uint8_t iei, uint8_t *buffer, uint32_t len)
{
  uint8_t *lenPtr;
  uint32_t encoded = 0;
  /* Checking IEI and pointer */
  CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, TRACKING_AREA_IDENTITY_LIST_MINIMUM_LENGTH, len);
#if defined (NAS_DEBUG)
  dump_tracking_area_identity_list_xml(trackingareaidentitylist, iei);
#endif

  if (iei > 0) {
    *buffer = iei;
    encoded++;
  }

  lenPtr  = (buffer + encoded);
  encoded ++;
  *(buffer + encoded) = 0x00 |
                        ((trackingareaidentitylist->typeoflist & 0x3) << 5) |
                        (trackingareaidentitylist->numberofelements & 0x1f);
  encoded++;
  *(buffer + encoded) = 0x00 | ((trackingareaidentitylist->mccdigit2 & 0xf) << 4) |
                        (trackingareaidentitylist->mccdigit1 & 0xf);
  encoded++;
  *(buffer + encoded) = 0x00 | ((trackingareaidentitylist->mncdigit3 & 0xf) << 4) |
                        (trackingareaidentitylist->mccdigit3 & 0xf);
  encoded++;
  *(buffer + encoded) = 0x00 | ((trackingareaidentitylist->mncdigit2 & 0xf) << 4) |
                        (trackingareaidentitylist->mncdigit1 & 0xf);
  encoded++;
  IES_ENCODE_U16(buffer, encoded, trackingareaidentitylist->tac);
  *lenPtr = encoded - 1 - ((iei > 0) ? 1 : 0);
  return encoded;
}
int encode_tracking_area_identity(TrackingAreaIdentity *trackingareaidentity, uint8_t iei, uint8_t *buffer, uint32_t len)
{
  uint32_t encoded = 0;
  /* Checking IEI and pointer */
  CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, TRACKING_AREA_IDENTITY_MINIMUM_LENGTH, len);
#if defined (NAS_DEBUG)
  dump_tracking_area_identity_xml(trackingareaidentity, iei);
#endif

  if (iei > 0) {
    *buffer = iei;
    encoded++;
  }

  *(buffer + encoded) = 0x00 | ((trackingareaidentity->mccdigit2 & 0xf) << 4) |
                        (trackingareaidentity->mccdigit1 & 0xf);
  encoded++;
  *(buffer + encoded) = 0x00 | ((trackingareaidentity->mncdigit3 & 0xf) << 4) |
                        (trackingareaidentity->mccdigit3 & 0xf);
  encoded++;
  *(buffer + encoded) = 0x00 | ((trackingareaidentity->mncdigit2 & 0xf) << 4) |
                        (trackingareaidentity->mncdigit1 & 0xf);
  encoded++;
  IES_ENCODE_U16(buffer, encoded, trackingareaidentity->tac);
  return encoded;
}
static int encode_traffic_flow_template_packet_filters(PacketFilters* packetfilters, uint8_t nbpacketfilters, uint8_t *buffer, uint32_t len)
{
    int encoded = 0, i, j;

    for (i = 0; (i < nbpacketfilters) && (len - encoded > 0); i++)
    {
	if (len - encoded <= 0) {
	    /* Mismatch between the number of packet filters subfield,
	     * and the number of packet filters in the packet filter list */
	    return (TLV_DECODE_VALUE_DOESNT_MATCH);
	}
	/* Packet filter identifier and direction */
	IES_ENCODE_U8(buffer, encoded, (0x00 | ((*packetfilters)[i].direction << 4) | ((*packetfilters)[i].identifier)));
	/* Packet filter evaluation precedence  */
	IES_ENCODE_U8(buffer, encoded, (*packetfilters)[i].eval_precedence);
	/* Save address of the Packet filter contents field length */
	uint8_t* pkflenPtr = buffer + encoded;
	encoded++;
	/* Packet filter contents */
	int pkfstart = encoded;
	uint16_t flag = TRAFFIC_FLOW_TEMPLATE_IPV4_REMOTE_ADDR_FLAG;
	while (flag <= TRAFFIC_FLOW_TEMPLATE_FLOW_LABEL_FLAG)
	{
	    switch ((*packetfilters)[i].packetfilter.flags & flag)
	    {
		case TRAFFIC_FLOW_TEMPLATE_IPV4_REMOTE_ADDR_FLAG:
		    /* IPv4 remote address type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_IPV4_REMOTE_ADDR);
		    for (j = 0; j < TRAFFIC_FLOW_TEMPLATE_IPV4_ADDR_SIZE; j++)
		    {
			*(buffer + encoded) = (*packetfilters)[i].packetfilter.ipv4remoteaddr[j].addr;
			*(buffer + encoded + TRAFFIC_FLOW_TEMPLATE_IPV4_ADDR_SIZE) = (*packetfilters)[i].packetfilter.ipv4remoteaddr[j].mask;
			encoded++;
		    }
		    encoded += TRAFFIC_FLOW_TEMPLATE_IPV4_ADDR_SIZE;
		    break;

		case TRAFFIC_FLOW_TEMPLATE_IPV6_REMOTE_ADDR_FLAG:
		    /* IPv6 remote address type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_IPV6_REMOTE_ADDR);
		    for (j = 0; j < TRAFFIC_FLOW_TEMPLATE_IPV6_ADDR_SIZE; j++)
		    {
			*(buffer + encoded) = (*packetfilters)[i].packetfilter.ipv6remoteaddr[j].addr;
			*(buffer + encoded + TRAFFIC_FLOW_TEMPLATE_IPV6_ADDR_SIZE) = (*packetfilters)[i].packetfilter.ipv6remoteaddr[j].mask;
			encoded++;
		    }
		    encoded += TRAFFIC_FLOW_TEMPLATE_IPV6_ADDR_SIZE;
		    break;

		case TRAFFIC_FLOW_TEMPLATE_PROTOCOL_NEXT_HEADER_FLAG:
		    /* Protocol identifier/Next header type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_PROTOCOL_NEXT_HEADER);
		    IES_ENCODE_U8(buffer, encoded, (*packetfilters)[i].packetfilter.protocolidentifier_nextheader);
		    break;

		case TRAFFIC_FLOW_TEMPLATE_SINGLE_LOCAL_PORT_FLAG:
		    /* Single local port type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_SINGLE_LOCAL_PORT);
		    IES_ENCODE_U16(buffer, encoded, (*packetfilters)[i].packetfilter.singlelocalport);
		    break;

		case TRAFFIC_FLOW_TEMPLATE_LOCAL_PORT_RANGE_FLAG:
		    /* Local port range type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_LOCAL_PORT_RANGE);
		    IES_ENCODE_U16(buffer, encoded, (*packetfilters)[i].packetfilter.localportrange.lowlimit);
		    IES_ENCODE_U16(buffer, encoded, (*packetfilters)[i].packetfilter.localportrange.highlimit);
		    break;

		case TRAFFIC_FLOW_TEMPLATE_SINGLE_REMOTE_PORT_FLAG:
		    /* Single remote port type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_SINGLE_REMOTE_PORT);
		    IES_ENCODE_U16(buffer, encoded, (*packetfilters)[i].packetfilter.singleremoteport);
		    break;

		case TRAFFIC_FLOW_TEMPLATE_REMOTE_PORT_RANGE_FLAG:
		    /* Remote port range type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_REMOTE_PORT_RANGE);
		    IES_ENCODE_U16(buffer, encoded, (*packetfilters)[i].packetfilter.remoteportrange.lowlimit);
		    IES_ENCODE_U16(buffer, encoded, (*packetfilters)[i].packetfilter.remoteportrange.highlimit);
		    break;

		case TRAFFIC_FLOW_TEMPLATE_SECURITY_PARAMETER_INDEX_FLAG:
		    /* Security parameter index type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_SECURITY_PARAMETER_INDEX);
		    IES_ENCODE_U32(buffer, encoded, (*packetfilters)[i].packetfilter.securityparameterindex);
		    break;

		case TRAFFIC_FLOW_TEMPLATE_TYPE_OF_SERVICE_TRAFFIC_CLASS_FLAG:
		    /* Type of service/Traffic class type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_TYPE_OF_SERVICE_TRAFFIC_CLASS);
		    IES_ENCODE_U8(buffer, encoded, (*packetfilters)[i].packetfilter.typdeofservice_trafficclass.value);
		    IES_ENCODE_U8(buffer, encoded, (*packetfilters)[i].packetfilter.typdeofservice_trafficclass.mask);
		    break;

		case TRAFFIC_FLOW_TEMPLATE_FLOW_LABEL_FLAG:
		    /* Flow label type */
		    IES_ENCODE_U8(buffer, encoded, TRAFFIC_FLOW_TEMPLATE_FLOW_LABEL);
		    IES_ENCODE_U24(buffer, encoded, (*packetfilters)[i].packetfilter.flowlabel & 0x000fffff);
		    break;

		default:
		    break;
	    }
	    flag = flag << 1;
	}
	/* Length of the Packet filter contents field  */
	*pkflenPtr = encoded - pkfstart;
    }

    return encoded;
}