update it

This commit is contained in:
Sukchan Lee 2017-03-11 22:25:58 +09:00
parent 3907a8062e
commit 7e0416c7ac
9 changed files with 11696 additions and 0 deletions

21
lib/gtp/Makefile.am Normal file
View File

@ -0,0 +1,21 @@
## Process this file with automake to produce Makefile.in
noinst_LTLIBRARIES = libgtp.la
libgtp_la_SOURCES = \
asn_msg.h asn_tlv_user.h asn_tlv_desc.h asn_msg_desc.h
nodist_libgtp_la_SOURCES = \
asn_msg.c
AM_CPPFLAGS = \
-I$(top_srcdir)/lib/core/include \
-I$(top_srcdir)/lib/3gpp
AM_CFLAGS = \
-Wall -Werror
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = *.stackdump
EXTRA_DIST = .libs $(noinst_LTLIBRARIES)

206
lib/gtp/asn_hdr.h Normal file
View File

@ -0,0 +1,206 @@
#ifndef __ASN_MHDR_H__
#define __ASN_MHDR_H__
#include "core.h"
#include "core_errno.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define ASN_FUNC_QOS 1
#define ASN_FUNC_HO_CTRL 2
#define ASN_FUNC_DP_CTRL 3
#define ASN_FUNC_CTX_TRAN 4
#define ASN_FUNC_R3_MOB 5
#define ASN_FUNC_PAGING 6
#define ASN_FUNC_RRM 7
#define ASN_FUNC_AUTH_RELAY 8
#define ASN_FUNC_MS_STATE 9
#define ASN_FUNC_IM_OPERATION 10
#define ASN_FUNC_ACCOUNTING 11
#define ASN_FUNC_BASE ASN_FUNC_QOS
#define ASN_FUNC_TOP ASN_FUNC_ACCOUNTING
/* 1 ASN_FUNC_QOS */
#define F1_RR_REQ 1
#define F1_RR_RSP 2
#define F1_RR_ACK 3
#define F1_BASE F1_RR_REQ
#define F1_TOP F1_RR_ACK
/* 2 ASN_FUNC_HO_CTRL */
#define F2_HO_REQ 1
#define F2_HO_RSP 2
#define F2_HO_ACK 3
#define F2_HO_CNF 4
#define F2_HO_COMPLETE 5
#define F2_HO_DIRECTIVE 6
#define F2_HO_DIRECTIVE_RSP 7
#define F2_BASE F2_HO_REQ
#define F2_TOP F2_HO_DIRECTIVE_RSP
/* 3 ASN_FUNC_DP_CTRL */
#define F3_PATH_DEREG_REQ 1
#define F3_PATH_DEREG_RSP 2
#define F3_PATH_DEREG_ACK 3
#define F3_PATH_MODIF_REQ 4
#define F3_PATH_MODIF_RSP 5
#define F3_PATH_MODIF_ACK 6
#define F3_PATH_PREREG_REQ 7
#define F3_PATH_PREREG_RSP 8
#define F3_PATH_PREREG_ACK 9
#define F3_PATH_REG_REQ 10
#define F3_PATH_REG_RSP 11
#define F3_PATH_REG_ACK 12
#define F3_IM_EXIT_STATE_IND 13
#define F3_IM_EXIT_STATE_IND_ACK 14
#define F3_BASE F3_PATH_DEREG_REQ
#define F3_TOP F3_IM_EXIT_STATE_IND_ACK
/* 4 ASN_FUNC_CTX_TRAN */
#define F4_CONTEXT_REQ 1
#define F4_CONTEXT_RPT 2
#define F4_CONTEXT_ACK 3
#define F4_CMAC_KEY_CNT_UPDATE 4
#define F4_CMAC_KEY_CNT_UPDATE_ACK 5
#define F4_PREPAID_REQ 8
#define F4_PREPAID_NOTIFY 9
#define F4_BASE F4_CONTEXT_REQ
#define F4_TOP F4_PREPAID_NOTIFY
/* 5 ASN_FUNC_R3_MOB */
#define F5_ANCHOR_DPF_HO_REQ 1
#define F5_ANCHOR_DPF_HO_TRIG 2
#define F5_ANCHOR_DPF_HO_RSP 3
#define F5_ANCHOR_DPF_RELOC_REQ 4
#define F5_ANCHOR_DPF_RELOC_RSP 5
#define F5_FA_REGISTER_REQ 6
#define F5_FA_REGISTER_RSP 7
#define F5_FA_REVOKE_REQ 8
#define F5_FA_REVOKE_RSP 9
#define F5_ANCHOR_DPF_RELEASE_REQ 10
#define F5_RELOC_READY_REQ 11
#define F5_RELOC_READY_RSP 12
#define F5_BASE F5_ANCHOR_DPF_HO_REQ
#define F5_TOP F5_RELOC_READY_RSP
/* 6 ASN_FUNC_PAGING */
#define F6_PAGING_ANNOUNCE 1
#define F6_DEL_MS_ENTRY_REQ 2
#define F6_PC_RELOC_IND 3
#define F6_PC_RELOC_ACK 4
#define F6_DEL_MS_ENTRY_RSP 5
#define F6_ANCHOR_PC_IND 6
#define F6_ANCHOR_PC_ACK 7
#define F6_BASE F6_PAGING_ANNOUNCE
#define F6_TOP F6_ANCHOR_PC_ACK
/* 7 ASN_FUNC_RRM */
#define F7_R6_PHY_PARAM_REQ 1
#define F7_R6_PHY_PARAM_RPT 2
#define F7_R4R6_SPARE_CAPA_REQ 3
#define F7_R4R6_SPARE_CAPA_RPT 4
#define F7_R6_NBR_BS_STATUS_UPDATE 5
#define F7_R4R6_RADIO_CONF_UPDATE_REQ 6
#define F7_R4R6_RADIO_CONF_UPDATE_RPT 7
#define F7_R4R6_RADIO_CONF_UPDATE_ACK 8
#define F7_BASE F7_R6_PHY_PARAM_REQ
#define F7_TOP F7_R4R6_RADIO_CONF_UPDATE_ACK
/* 8 ASN_FUNC_AUTH_RELAY */
#define F8_AR_EAP_START 1
#define F8_AR_EAP_TRANSFER 2
#define F8_BULK_INTERIM_UPDATE 3
#define F8_BULK_INTERIM_UPDATE_ACK 4
#define F8_BASE F8_AR_EAP_START
#define F8_TOP F8_BULK_INTERIM_UPDATE_ACK
/* 9 ASN_FUNC_MS_STATE */
#define F9_MS_PRE_ATTACH_REQ 1
#define F9_MS_PRE_ATTACH_RSP 2
#define F9_MS_PRE_ATTACH_ACK 3
#define F9_MS_ATTACH_REQ 4
#define F9_MS_ATTACH_RSP 5
#define F9_MS_ATTACH_ACK 6
#define F9_KEY_CHANGE_DIRECTIVE 7
#define F9_KEY_CHANGE_CNF 8
#define F9_KEY_CHANGE_ACK 9
#define F9_RELOC_COMPLETE_REQ 10
#define F9_RELOC_COMPLETE_RSP 11
#define F9_RELOC_COMPLETE_ACK 12
#define F9_RELOC_NOTIFY 13
#define F9_RELOC_REQ 14
#define F9_RELOC_RSP 15
#define F9_NETEXIT_MS_STATE_CHANGE_REQ 16
#define F9_NETEXIT_MS_STATE_CHANGE_RSP 17
#define F9_RELOC_NOTIFY_RSP 18
#define F9_BASE F9_MS_PRE_ATTACH_REQ
#define F9_TOP F9_RELOC_NOTIFY_RSP
/* 10 ASN_FUNC_IM_OPERATION */
#define F10_IM_ENTRY_STATE_CHANGE_REQ 1
#define F10_IM_ENTRY_STATE_CHANGE_RSP 2
#define F10_IM_ENTRY_STATE_CHANGE_ACK 3
#define F10_IM_EXIT_STATE_CHANGE_REQ 4
#define F10_IM_EXIT_STATE_CHANGE_RSP 5
#define F10_INIT_PAGING_REQ 6
#define F10_INIT_PAGING_RSP 7
#define F10_LU_REQ 8
#define F10_LU_RSP 9
#define F10_LU_CNF 10
#define F10_BASE F10_IM_ENTRY_STATE_CHANGE_REQ
#define F10_TOP F10_LU_CNF
/* 11 ASN_FUNC_ACCOUNTING */
#define F11_HOT_LINING_REQ 1
#define F11_HOT_LINING_RSP 2
#define F11_BASE F11_HOT_LINING_REQ
#define F11_TOP F11_HOT_LINING_RSP
typedef struct _asn_hdr_t {
#define ASN_HDR_VER_1 0x01
c_uint8_t version;
#define ASN_HDR_FLAG_RESTART 0x01 /**< Restart next expected transaction ID */
#define ASN_HDR_FLAG_RELAY 0x02 /**< Relay mode of operation */
#define ASN_HDR_FLAG_LEGACY 0x04 /**< 0: Sender is a lagacy node, 1: not legacy */
#define ASN_HDR_FLAG_COMP 0x08 /**< Comprehension is required for function type, OP ID and message type */
#define ASN_HDR_FLAG_ERR 0x10 /**< 1: Error reflection message, 0: not */
c_uint8_t flags;
c_uint8_t ftype;
#define ASN_HDR_OPID_REQ 0x01
#define ASN_HDR_OPID_RSP 0x02
#define ASN_HDR_OPID_ACK 0x03
#define ASN_HDR_OPID_IND 0x04
#define ASN_HDR_OPID_RSVD1 0x05
#define ASN_HDR_OPID_RSVD2 0x06
#define ASN_HDR_OPID_RSVD3 0x07
ED2(c_uint8_t opid:3;,
c_uint8_t mtype:5;)
c_uint16_t length;
c_uint8_t msid[6];
c_uint32_t reserved1;
c_uint16_t trns_id;
c_uint16_t reserved2;
} __attribute__ ((packed)) asn_hdr_t;
#define ASN_HEADER_LEN 20 /* size of asn_hdr_t */
typedef struct _asn_hdr_desc_t {
c_uint8_t flags;
c_uint8_t ftype;
c_uint8_t opid;
c_uint8_t mtype;
c_uint8_t msid[6];
c_uint16_t trns_id;
} asn_hdr_desc_t;
extern char asn_func_type_str[][16];
extern char asn_opid_str[][4];
extern char asn_msg_type_str[][19][32];
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !__ASN_MHDR_H__ */

565
lib/gtp/asn_msg.c Normal file
View File

@ -0,0 +1,565 @@
#define TRACE_MODULE _asn_msg
#include "core_debug.h"
#include "core_tlv.h"
#include "asn_hdr.h"
#include "asn_msg.h"
#include "netinet/in.h"
#include "asn_tlv_desc.c"
#include "asn_msg_desc.c"
asnt_desc_t asnt_more =
{
ASNC_MORE, 0, ASNL_MORE, 0, { NULL }
};
static tlv_t* _asn_add_leaf(tlv_t *parent_tlv, tlv_t *tlv, asnt_desc_t *desc,
void *asnv)
{
switch (desc->ctype)
{
case ASNC_UINT8:
case ASNC_INT8:
{
asnv_uint8_t *v = (asnv_uint8_t *)asnv;
d_trace(1, "V_1B:%02x", v->v);
if (parent_tlv)
tlv = tlv_embed(parent_tlv, desc->type, 1, 0, (c_uint8_t*)&v->v);
else
tlv = tlv_add(tlv, desc->type, 1, 0, (c_uint8_t*)&v->v);
d_assert(tlv, return NULL, "Can't add TLV");
break;
}
case ASNC_UINT16:
{
asnv_uint16_t *v = (asnv_uint16_t *)asnv;
d_trace(1, "V_2B:%04x", v->v);
v->v = htons(v->v);
if (parent_tlv)
tlv = tlv_embed(parent_tlv, desc->type, 2, 0, (c_uint8_t*)&v->v);
else
tlv = tlv_add(tlv, desc->type, 2, 0, (c_uint8_t*)&v->v);
d_assert(tlv, return NULL, "Can't add TLV");
break;
}
case ASNC_UINT24:
case ASNC_INT24:
{
asnv_uint24_t *v = (asnv_uint24_t *)asnv;
d_trace(1, "V_3B:%06x", v->v);
v->v = v->v << 8;
v->v = htonl(v->v);
if (parent_tlv)
tlv = tlv_embed(parent_tlv, desc->type, 3, 0, (c_uint8_t*)&v->v);
else
tlv = tlv_add(tlv, desc->type, 3, 0, (c_uint8_t*)&v->v);
d_assert(tlv, return NULL, "Can't add TLV");
break;
}
case ASNC_UINT32:
case ASNC_INT32:
{
asnv_uint32_t *v = (asnv_uint32_t *)asnv;
d_trace(1, "V_4B:%08x", v->v);
v->v = htonl(v->v);
if (parent_tlv)
tlv = tlv_embed(parent_tlv, desc->type, 4, 0, (c_uint8_t*)&v->v);
else
tlv = tlv_add(tlv, desc->type, 4, 0, (c_uint8_t*)&v->v);
d_assert(tlv, return NULL, "Can't add TLV");
break;
}
case ASNC_FIXED_STR:
{
asnv_octets_t *v = (asnv_octets_t *)asnv;
d_trace(1, "V_FSTR: ", v->v);
d_trace_hex(1, v->v, v->l);
if (parent_tlv)
tlv = tlv_embed(parent_tlv, desc->type, desc->length, 0, v->v);
else
tlv = tlv_add(tlv, desc->type, desc->length, 0, v->v);
d_assert(tlv, return NULL, "Can't add TLV");
break;
}
case ASNC_VAR_STR:
{
asnv_octets_t *v = (asnv_octets_t *)asnv;
d_assert(v->l > 0, return NULL, "Length is zero");
d_trace(1, "V_VSTR: ", v->v);
d_trace_hex(1, v->v, v->l);
if (parent_tlv)
tlv = tlv_embed(parent_tlv, desc->type, v->l, 0, v->v);
else
tlv = tlv_add(tlv, desc->type, v->l, 0, v->v);
d_assert(tlv, return NULL, "Can't add TLV");
break;
}
case ASNC_NULL:
{
d_trace(1, "V_NULL" );
if (parent_tlv)
tlv = tlv_embed(parent_tlv, desc->type, 0, 0, NULL);
else
tlv = tlv_add(tlv, desc->type, 0, 0, NULL);
d_assert(tlv, return NULL, "Can't add TLV");
break;
}
default:
{
d_assert(0, return NULL, "Unknown class %d", desc->ctype);
break;
}
}
return tlv;
}
static c_uint32_t _asn_add_compound(tlv_t **root, tlv_t *parent_tlv,
asnt_desc_t *parent_desc, void *asnv, int depth)
{
asnv_header_t *h;
asnt_desc_t *desc = NULL, *next_desc = NULL;
tlv_t *tlv = NULL, *emb_tlv = NULL;
c_uint8_t *p = asnv;
c_uint32_t offset = 0, count = 0;
int i, j, r;
char indent[17] = " "; /* 16 spaces */
d_assert(root, return 0, "Null param");
d_assert(parent_desc, return 0, "Null param");
d_assert(asnv, return 0, "Null param");
d_assert(depth <= 8, return 0, "Too deep recursion");
indent[depth*2] = 0;
*root = NULL;
for (i = 0, desc = parent_desc->child_descs[i]; desc != NULL;
i++, desc = parent_desc->child_descs[i])
{
next_desc = parent_desc->child_descs[i+1];
if (next_desc != NULL && next_desc->ctype == ASNC_MORE)
{
int offset2 = offset;
for (j = 0; j < next_desc->length; j++)
{
h = (asnv_header_t *)(p + offset2);
if (h->set_ind == 0)
break;
if (desc->ctype == ASNC_COMPOUND)
{
d_trace(1, "\nBUILD %sC#%d T:%d (vsz=%d) off:%p ",
indent, i, desc->type, desc->vsize, p + offset);
if (parent_tlv)
tlv = tlv_embed(parent_tlv, desc->type, 0, 0, NULL);
else
tlv = tlv_add(tlv, desc->type, 0, 0, NULL);
r = _asn_add_compound(&emb_tlv, tlv, desc,
p + offset + sizeof(asnv_header_t), depth + 1);
d_assert(r > 0 && emb_tlv, return 0,
"Can't build compound TLV");
count += 1 + r;
}
else
{
d_trace(1, "\nBUILD %sL#%d T:%d L:%d (cls:%d vsz:%d) off:%p ",
indent, i, desc->type, desc->length,
desc->ctype, desc->vsize, p + offset);
tlv = _asn_add_leaf(parent_tlv, tlv, desc, p + offset);
d_assert(tlv, return 0, "Can't build leaf TLV");
count++;
}
if (*root == NULL)
*root = tlv;
offset2 += desc->vsize;
}
offset += desc->vsize * next_desc->length;
i++;
}
else
{
h = (asnv_header_t *)(p + offset);
if (h->set_ind)
{
if (desc->ctype == ASNC_COMPOUND)
{
d_trace(1, "\nBUILD %sC#%d T:%d (vsz=%d) off:%p ",
indent, i, desc->type, desc->vsize, p + offset);
if (parent_tlv)
tlv = tlv_embed(parent_tlv, desc->type, 0, 0, NULL);
else
tlv = tlv_add(tlv, desc->type, 0, 0, NULL);
r = _asn_add_compound(&emb_tlv, tlv, desc,
p + offset + sizeof(asnv_header_t), depth + 1);
d_assert(r > 0 && emb_tlv, return 0,
"Can't build compound TLV");
count += 1 + r;
}
else
{
d_trace(1, "\nBUILD %sL#%d T:%d L:%d (cls:%d vsz:%d) off:%p ",
indent, i, desc->type, desc->length,
desc->ctype, desc->vsize, p + offset);
tlv = _asn_add_leaf(parent_tlv, tlv, desc, p + offset);
d_assert(tlv, return 0, "Can't build leaf TLV");
count++;
}
if (*root == NULL)
*root = tlv;
}
offset += desc->vsize;
}
}
return count;
}
status_t asn_build_msg(pkbuf_t **msg, asn_msg_desc_t *msg_desc, void *asnv)
{
tlv_t *root = NULL;
c_uint32_t r, length, rendlen;
d_assert(msg, return CORE_ERROR, "Null param");
d_assert(msg_desc, return CORE_ERROR, "Null param");
d_assert(asnv, return CORE_ERROR, "Null param");
d_assert(msg_desc->ctype == ASNC_MESSAGE, return CORE_ERROR,
"Not ASN message descriptor");
d_assert(msg_desc->child_descs[0], return CORE_ERROR,
"ASN message descriptor has no members");
r = _asn_add_compound(&root, NULL, msg_desc, asnv, 0);
d_assert(r > 0 && root, tlv_free_all(root); return CORE_ERROR,
"Can't build ASN message");
length = tlv_calc_length(root, TLV_MODE_T1_L2_I1);
*msg = pkbuf_alloc(ASN_HEADER_LEN, length);
d_assert(*msg, tlv_free_all(root); return CORE_ENOMEM,
"pkbuf_alloc() failed");
(*msg)->len = length;
rendlen = tlv_render(root, (*msg)->payload, length, TLV_MODE_T1_L2_I1);
d_assert(rendlen == length, tlv_free_all(root); return CORE_ERROR,
"Error while render TLV (%d != %d)", length, rendlen);
tlv_free_all(root);
return CORE_OK;
}
static asnt_desc_t* _asn_find_desc(c_uint8_t *asnt_index,
c_uint32_t *asnv_offset, asnt_desc_t *parent_desc, tlv_t *tlv)
{
asnt_desc_t *prev_desc = NULL, *desc = NULL;
int i, offset = 0;
d_assert(parent_desc, return NULL, "Null param");
d_assert(tlv, return NULL, "Null param");
d_trace(5, "_asn_find_desc:%d - ", tlv->type);
for (i = 0, desc = parent_desc->child_descs[i]; desc != NULL;
i++, desc = parent_desc->child_descs[i])
{
d_trace(5, "%d, ", desc->type);
if (desc->type == tlv->type)
{
*asnt_index = i;
*asnv_offset = offset;
break;
}
if (desc->ctype == ASNC_MORE)
{
d_assert(prev_desc && prev_desc->ctype != ASNC_MORE,
return NULL, "Invalid previous asnt_desc_t");
offset += prev_desc->vsize * (desc->length - 1);
}
else
{
offset += desc->vsize;
}
prev_desc = desc;
}
d_trace(5, "\n");
return desc;
}
static status_t _asn_parse_leaf(
void *asnv, asnt_desc_t *desc, tlv_t *tlv)
{
d_assert(asnv, return CORE_ERROR, "Null param");
d_assert(desc, return CORE_ERROR, "Null param");
d_assert(tlv, return CORE_ERROR, "Null param");
switch (desc->ctype)
{
case ASNC_UINT8:
case ASNC_INT8:
{
asnv_uint8_t *v = (asnv_uint8_t *)asnv;
if (tlv->length != 1)
{
d_error("Invalid TLV length %d. It should be 1", tlv->length);
return CORE_ERROR;
}
v->v = *(c_uint8_t*)(tlv->value);
d_trace(1, "V_1B:%02x", v->v);
break;
}
case ASNC_UINT16:
case ASNC_INT16:
{
asnv_uint16_t *v = (asnv_uint16_t *)asnv;
if (tlv->length != 2)
{
d_error("Invalid TLV length %d. It should be 2", tlv->length);
return CORE_ERROR;
}
v->v = ((((c_uint8_t*)tlv->value)[0]<< 8)&0xff00) |
((((c_uint8_t*)tlv->value)[1] )&0x00ff);
d_trace(1, "V_2B:%02x", v->v);
break;
}
case ASNC_UINT24:
case ASNC_INT24:
{
asnv_uint24_t *v = (asnv_uint24_t *)asnv;
if (tlv->length != 3)
{
d_error("Invalid TLV length %d. It should be 3", tlv->length);
return CORE_ERROR;
}
v->v = ((((c_uint8_t*)tlv->value)[0]<<16)&0x00ff0000) |
((((c_uint8_t*)tlv->value)[1]<< 8)&0x0000ff00) |
((((c_uint8_t*)tlv->value)[2] )&0x000000ff);
d_trace(1, "V_3B:%06x", v->v);
break;
}
case ASNC_UINT32:
case ASNC_INT32:
{
asnv_uint32_t *v = (asnv_uint32_t *)asnv;
if (tlv->length != 4)
{
d_error("Invalid TLV length %d. It should be 4", tlv->length);
return CORE_ERROR;
}
v->v = ((((c_uint8_t*)tlv->value)[0]<<24)&0xff000000) |
((((c_uint8_t*)tlv->value)[1]<<16)&0x00ff0000) |
((((c_uint8_t*)tlv->value)[2]<< 8)&0x0000ff00) |
((((c_uint8_t*)tlv->value)[3] )&0x000000ff);
d_trace(1, "V_4B:%08x", v->v);
break;
}
case ASNC_FIXED_STR:
{
asnv_octets_t *v = (asnv_octets_t *)asnv;
if (tlv->length != desc->length)
{
d_error("Invalid TLV length %d. It should be %d",
tlv->length, desc->length);
return CORE_ERROR;
}
v->v = tlv->value;
v->l = tlv->length;
d_trace(1, "V_FSTR: ", v->v);
d_trace_hex(1, v->v, v->l);
break;
}
case ASNC_VAR_STR:
{
asnv_octets_t *v = (asnv_octets_t *)asnv;
v->v = tlv->value;
v->l = tlv->length;
d_trace(1, "V_VSTR: ", v->v);
d_trace_hex(1, v->v, v->l);
break;
}
case ASNC_NULL:
{
if (tlv->length != 0)
{
d_error("Invalid TLV length %d. It should be 0", tlv->length);
return CORE_ERROR;
}
break;
}
default:
d_assert(0, return CORE_ERROR, "Unknown TLV class");
break;
}
return CORE_OK;
}
static status_t _asn_parse_compound(
void *asnv, asnt_desc_t *parent_desc, tlv_t *parent_tlv, int depth)
{
status_t rv;
asnv_header_t *h = (asnv_header_t *)asnv;
asnt_desc_t *desc = NULL, *next_desc = NULL;
tlv_t *tlv = NULL, *emb_tlv = NULL;
c_uint8_t *p = asnv;
c_uint32_t offset = 0;
c_uint8_t index = 0;
int i = 0, j;
char indent[17] = " "; /* 16 spaces */
d_assert(asnv, return CORE_ERROR, "Null param");
d_assert(parent_desc, return CORE_ERROR, "Null param");
d_assert(parent_tlv, return CORE_ERROR, "Null param");
d_assert(depth <= 8, return 0, "Too deep recursion");
indent[depth*2] = 0;
tlv = parent_tlv;
while(tlv)
{
desc = _asn_find_desc(&index, &offset, parent_desc, tlv);
if (desc == NULL)
{
d_error("Unexpected TLV type:%d", tlv->type);
return CORE_ERROR;
}
h = (asnv_header_t *)(p + offset);
/* Multiple of the same type TLV may be included */
next_desc = parent_desc->child_descs[index+1];
if (next_desc != NULL && next_desc->ctype == ASNC_MORE)
{
for (j = 0; j < next_desc->length; j++)
{
h = (asnv_header_t *)(p + offset + desc->vsize * j);
if (h->set_ind == 0)
{
offset += desc->vsize * j;
break;
}
}
if (j == next_desc->length)
{
d_fatal("Multiple of the same type TLV need more room");
tlv = tlv->next;
continue;
}
}
if (desc->ctype == ASNC_COMPOUND)
{
emb_tlv = tlv_parse_embedded_block(tlv, TLV_MODE_T1_L2_I1);
if (emb_tlv == NULL)
{
d_error("Error while parse TLV");
return CORE_ERROR;
}
d_trace(1, "\nPARSE %sC#%d T:%d (vsz=%d) off:%p ",
indent, i++, desc->type, desc->vsize, p + offset);
offset += sizeof(asnv_header_t);
rv = _asn_parse_compound(p + offset, desc, emb_tlv, depth + 1);
if (rv != CORE_OK)
{
d_error("Can't parse compound TLV");
return CORE_ERROR;
}
h->set_ind = 1;
}
else
{
d_trace(1, "\nPARSE %sL#%d T:%d L:%d (cls:%d vsz:%d) off:%p ",
indent, i++, desc->type, desc->length,
desc->ctype, desc->vsize, p + offset);
rv = _asn_parse_leaf(p + offset, desc, tlv);
if (rv != CORE_OK)
{
d_error("Can't parse leaf TLV");
return CORE_ERROR;
}
h->set_ind = 1;
}
tlv = tlv->next;
}
d_trace(1, "\n");
return CORE_OK;
}
status_t asn_parse_msg(void *asnv, asn_msg_desc_t *msg_desc, pkbuf_t *msg)
{
status_t rv;
tlv_t *root;
d_assert(asnv, return CORE_ERROR, "Null param");
d_assert(msg_desc, return CORE_ERROR, "Null param");
d_assert(msg, return CORE_ERROR, "Null param");
d_assert(msg_desc->ctype == ASNC_MESSAGE, return CORE_ERROR,
"Not ASN message descriptor");
d_assert(msg_desc->child_descs[0], return CORE_ERROR,
"ASN message descriptor has no members");
root = tlv_parse_block(msg->len, msg->payload, TLV_MODE_T1_L2_I1);
if (root == NULL)
{
d_error("Can't parse ASN message");
return CORE_ERROR;
}
rv = _asn_parse_compound(asnv, msg_desc, root, 0);
tlv_free_all(root);
return rv;
}

154
lib/gtp/asn_msg.h Normal file
View File

@ -0,0 +1,154 @@
#ifndef __ASN_MSG_H__
#define __ASN_MSG_H__
#include "core.h"
#include "core_pkbuf.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct _asnv_header_t {
c_uint32_t set_ind;
} asnv_header_t;
#define VALUE_SET(__m, __value) \
__m.v = __value; __m.h.set_ind = 1
#define OCTET_SET(__m, __value, __length) \
__m.v = __value; __m.l = __length; __m.h.set_ind = 1
#define COMPD_SET(__m) __m.h.set_ind = 1
#define VALUE_UNSET(__m) \
__m.h.set_ind = 0
#define VALUE_ISSET(__m) \
__m.h.set_ind
#define OCTET_ISSET(__asnv) VALUE_ISSET(__asnv)
#define COMPD_ISSET(__asnv) VALUE_ISSET(__asnv)
#define VALUE_GET(__asnv) (__asnv).v
#define VALUE_COPY(__t_asnv, __s_asnv) \
(__t_asnv).h = (__s_asnv).h; (__t_asnv).v = (__s_asnv).v
#define OCTET_GET(__value, __length, __asnv) \
__value = (__asnv).v; __length = (__asnv).l
#define OCTET_COPY(__t_asnv, __s_asnv) \
(__t_asnv).h = (__s_asnv).h; (__t_asnv).v = (__s_asnv).v; \
(__t_asnv).l = (__s_asnv).l
typedef enum {
ASNC_UINT8,
ASNC_UINT16,
ASNC_UINT24,
ASNC_UINT32,
ASNC_INT8,
ASNC_INT16,
ASNC_INT24,
ASNC_INT32,
ASNC_FIXED_STR,
ASNC_VAR_STR,
ASNC_NULL,
ASNC_MORE,
ASNC_COMPOUND,
ASNC_MESSAGE,
} asnc_type_e;
typedef struct _asnt_desc_t {
asnc_type_e ctype;
c_uint16_t type;
c_uint16_t length;
c_uint16_t vsize;
void *child_descs[];
} asnt_desc_t;
typedef asnt_desc_t asn_msg_desc_t;
/* 8-bit Unsigned integer */
typedef struct _asnv_uint8_t {
asnv_header_t h;
c_uint8_t v;
c_uint8_t dummy[3]; /* for 4 bytes align */
} asnv_uint8_t;
/* 16-bit Unsigned integer */
typedef struct _asnv_uint16t {
asnv_header_t h;
c_uint16_t v;
c_uint8_t dummy[2]; /* for 4 bytes align */
} asnv_uint16_t;
/* 24-bit Unsigned integer */
typedef struct _asnv_uint24t {
asnv_header_t h;
c_uint32_t v; /* Only 3 bytes valid */
} asnv_uint24_t;
/* 32-bit Unsigned integer */
typedef struct _asnv_uint32t {
asnv_header_t h;
c_uint32_t v;
} asnv_uint32_t;
/* 8-bit Signed integer */
typedef struct _asnv_int8_t {
asnv_header_t h;
c_int8_t v;
c_uint8_t dummy[3]; /* for 4 bytes align */
} asnv_int8_t;
/* 16-bit Signed integer */
typedef struct _asnv_int16t {
asnv_header_t h;
c_int16_t v;
c_uint8_t dummy[2]; /* for 4 bytes align */
} asnv_int16_t;
/* 24-bit Signed integer */
typedef struct _asnv_int24t {
asnv_header_t h;
c_int32_t v; /* Only 3 bytes valid */
} asnv_int24_t;
/* 32-bit Signed integer */
typedef struct _asnv_int32t {
asnv_header_t h;
c_int32_t v;
} asnv_int32_t;
/* Octets */
typedef struct _asnv_octets_t {
asnv_header_t h;
c_uint8_t *v;
c_uint32_t l;
} asnv_octets_t;
/* No value */
typedef struct _asnv_null {
asnv_header_t h;
} asnv_null_t;
#define ASNL_MORE 8
#define ASNV_1_OR_MORE(__v) __v[ASNL_MORE]
extern asnt_desc_t asnt_more;
CORE_DECLARE(status_t) asn_build_msg(
pkbuf_t **msg, asn_msg_desc_t *msg_desc, void *asnv);
CORE_DECLARE(status_t) asn_parse_msg(
void *asnv, asn_msg_desc_t *msg_desc, pkbuf_t *msg);
#include "asn_tlv_desc.h"
#include "asn_msg_desc.h"
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !__ASN_MSG_H__ */

109
lib/gtp/asn_msg_desc.c Normal file
View File

@ -0,0 +1,109 @@
asn_msg_desc_t asnt_msg_ms_preattachment_req = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_ms_info,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_ms_preattachment_rsp = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_failure_indication,
&asnt_ms_info,
&asnt_ms_security_history,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_ms_attachment_req = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_ms_info,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_ms_attachment_rsp = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_failure_indication,
&asnt_ms_info,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_path_reg_req = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_registration_type,
&asnt_ms_info,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_path_reg_rsp = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_failure_indication,
&asnt_registration_type,
&asnt_ms_info,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_path_reg_ack = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_failure_indication,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_rr_req = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_ms_info,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_rr_rsp = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_failure_indication,
&asnt_ms_info,
NULL,
}};
asn_msg_desc_t asnt_msg_rr_ack = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_failure_indication,
&asnt_ms_info,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_fa_reg_req = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_rrq,
NULL,
}};
asn_msg_desc_t asnt_msg_fa_reg_rsp = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_rrp,
NULL,
}};
asn_msg_desc_t asnt_msg_key_change_directive = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_bs_info,
&asnt_authentication_complete,
NULL,
}};
asn_msg_desc_t asnt_msg_key_change_cnf = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_failure_indication,
&asnt_ms_info,
&asnt_bs_info,
NULL,
}};
asn_msg_desc_t asnt_msg_key_change_ack = {
ASNC_MESSAGE, 0, 0, 0, {
&asnt_failure_indication,
NULL,
}};

114
lib/gtp/asn_msg_desc.h Normal file
View File

@ -0,0 +1,114 @@
typedef struct _asnv_msg_ms_preattachment_req {
asnv_ms_info_t ms_info;
asnv_bs_info_t bs_info;
} asnv_msg_ms_preattachment_req;
extern asn_msg_desc_t asnt_msg_ms_preattachment_req;
typedef struct _asnv_msg_ms_preattachment_rsp {
asnv_failure_indication_t failure_indication;
asnv_ms_info_t ms_info;
asnv_ms_security_history_t ms_security_history;
asnv_bs_info_t bs_info;
} asnv_msg_ms_preattachment_rsp;
extern asn_msg_desc_t asnt_msg_ms_preattachment_rsp;
typedef struct _asnv_msg_ms_attachment_req {
asnv_ms_info_t ms_info;
asnv_bs_info_t bs_info;
} asnv_msg_ms_attachment_req;
extern asn_msg_desc_t asnt_msg_ms_attachment_req;
typedef struct _asnv_msg_ms_attachment_rsp {
asnv_failure_indication_t failure_indication;
asnv_ms_info_t ms_info;
asnv_bs_info_t bs_info;
} asnv_msg_ms_attachment_rsp;
extern asn_msg_desc_t asnt_msg_ms_attachment_rsp;
typedef struct _asnv_msg_path_reg_req {
asnv_registration_type_t registration_type;
asnv_ms_info_t ms_info;
asnv_bs_info_t bs_info;
} asnv_msg_path_reg_req;
extern asn_msg_desc_t asnt_msg_path_reg_req;
typedef struct _asnv_msg_path_reg_rsp {
asnv_failure_indication_t failure_indication;
asnv_registration_type_t registration_type;
asnv_ms_info_t ms_info;
asnv_bs_info_t bs_info;
} asnv_msg_path_reg_rsp;
extern asn_msg_desc_t asnt_msg_path_reg_rsp;
typedef struct _asnv_msg_path_reg_ack {
asnv_failure_indication_t failure_indication;
asnv_bs_info_t bs_info;
} asnv_msg_path_reg_ack;
extern asn_msg_desc_t asnt_msg_path_reg_ack;
typedef struct _asnv_msg_rr_req {
asnv_ms_info_t ms_info;
asnv_bs_info_t bs_info;
} asnv_msg_rr_req;
extern asn_msg_desc_t asnt_msg_rr_req;
typedef struct _asnv_msg_rr_rsp {
asnv_failure_indication_t failure_indication;
asnv_ms_info_t ms_info;
} asnv_msg_rr_rsp;
extern asn_msg_desc_t asnt_msg_rr_rsp;
typedef struct _asnv_msg_rr_ack {
asnv_failure_indication_t failure_indication;
asnv_ms_info_t ms_info;
asnv_bs_info_t bs_info;
} asnv_msg_rr_ack;
extern asn_msg_desc_t asnt_msg_rr_ack;
typedef struct _asnv_msg_fa_reg_req {
asnv_rrq_t rrq;
#if 0 /* FIXME: */
asnv_fa_ha_key_t fa_ha_key;
asnv_fa_ha_key_lifetime_t fa_ha_lifetime;
asnv_fa_ha_key_spi_t fa_ha_spi;
#endif
} asnv_msg_fa_reg_req;
extern asn_msg_desc_t asnt_msg_fa_reg_req;
typedef struct _asnv_msg_fa_reg_rsp {
asnv_rrp_t rrp;
} asnv_msg_fa_reg_rsp;
extern asn_msg_desc_t asnt_msg_fa_reg_rsp;
typedef struct _asnv_msg_key_change_directive {
asnv_bs_info_t bs_info;
asnv_authentication_complete_t authentication_complete;
} asnv_msg_key_change_directive;
extern asn_msg_desc_t asnt_msg_key_change_directive;
typedef struct _asnv_msg_key_change_cnf {
asnv_failure_indication_t failure_indication;
asnv_ms_info_t ms_info;
asnv_bs_info_t bs_info;
} asnv_msg_key_change_cnf;
extern asn_msg_desc_t asnt_msg_key_change_cnf;
typedef struct _asnv_msg_key_change_ack {
asnv_failure_indication_t failure_indication;
} asnv_msg_key_change_ack;
extern asn_msg_desc_t asnt_msg_key_change_ack;

4013
lib/gtp/asn_tlv_desc.c Normal file

File diff suppressed because it is too large Load Diff

6401
lib/gtp/asn_tlv_desc.h Normal file

File diff suppressed because it is too large Load Diff

113
lib/gtp/asn_tlv_user.h Normal file
View File

@ -0,0 +1,113 @@
#define MAX_ASN_TYPE 372
#define ASNL_VARIABLE 0
#define ASNL_AUTHENTICATOR_IPV4 4
#define ASNL_AUTHENTICATOR_80216 6
#define ASNL_AUTHENTICATOR_IPV6 16
#define ASNL_AUTHENTICATOR_MAX ASNL_AUTHENTICATOR_IPV6
#define ASNV_AUTH_POLICY_SUPPORT_RSA 0x01
#define ASNV_AUTH_POLICY_SUPPORT_EAP 0x02
#define ASNV_AUTH_POLICY_SUPPORT_AEAP 0x04
#define ASNV_AUTH_POLICY_SUPPORT_RE_RSA 0x10
#define ASNV_AUTH_POLICY_SUPPORT_RE_EAP 0x20
#define ASNV_AUTH_POLICY_SUPPORT_RE_AEAP 0x40
#define ASNL_BSID_IPV4 4
#define ASNL_BSID_80216 6
#define ASNL_BSID_IPV6 16
#define ASNL_BSID_MAX ASNL_BSID_IPV6
#define ASNV_FAILURE_IND_UNSPECIFIED 0x00 /* Unspecified Error */
/* Error Codes: 0x01-0x0F Message Header Failure Codes */
#define ASNV_FAILURE_IND_PROTOCOL_VERSION 0x01 /* Protocol Version not understood (note 1) */
#define ASNV_FAILURE_IND_UNRECOG_FUNC_TYPE 0x02 /* Unrecognised Function Type */
#define ASNV_FAILURE_IND_INVALID_MSG_TYPE 0x03 /* Invalid Message Type */
#define ASNV_FAILURE_IND_UNKNOWN_MSID 0x04 /* Unknown MSID */
#define ASNV_FAILURE_IND_TRANSACTION 0x05 /* Transaction Failure */
#define ASNV_FAILURE_IND_UNKNOWN_SRC_ID 0x06 /* Source Identifier unknown or inconsistent with the IP source address */
#define ASNV_FAILURE_IND_UNKNOWN_DEST_ID 0x07 /* Destination unknown */
#define ASNV_FAILURE_IND_INVALID_HEADER 0x08 /* Invalid Message Header */
#define ASNV_FAILURE_IND_INVALID_OPID 0x09 /* Invalid OP ID */
#define ASNV_FAILURE_IND_NOORERR_DEST_ID 0x0A /* Destination Identifier missing or erroneous */
#define ASNV_FAILURE_IND_NOORERR_SRC_ID 0x0B /* Source Identifier TLV missing or erroneous */
#define ASNV_FAILURE_IND_UNKNOWN_MSG_TYPE 0x0C /* Message type unknown or inopportune */
#define ASNV_FAILURE_IND_UNRESOLVED_ERR 0x0D /* Unresolved error */
/* Error Codes: 0x10-0x1F General Message Body Failure Codes */
#define ASNV_FAILURE_IND_INVALID_MSG_FORMAT 0x10 /* Invalid message format */
#define ASNV_FAILURE_IND_NO_MANDATORY_TLV 0x11 /* Mandatory TLV missing */
#define ASNV_FAILURE_IND_INVALID_TLV_VALUE 0x12 /* TLV Value Invalid */
#define ASNV_FAILURE_IND_UNSUPPORTED_OPTION 0x13 /* Unsupported Options */
#define ASNV_FAILURE_IND_UNKNOWN_TLV 0x14 /* TLV Unknown */
#define ASNV_FAILURE_IND_UNEXPECTED_TLV 0x15 /* TLV Unexpected */
#define ASNV_FAILURE_IND_TLV_PARSE_ERROR 0x16 /* TLV parsing error */
/* Error Codes: 0x20-0x2F Message Generic Failure Codes */
#define ASNV_FAILURE_IND_TIMER_EXPIRED 0x20 /* Timer expired without response */
#define ASNV_FAILURE_IND_BSID_OUT_OF_SERVICE 0x21 /* BSID out of service */
#define ASNV_FAILURE_IND_UNKNOWN_BSID 0x22 /* Unknown BSID */
#define ASNV_FAILURE_IND_UNREACHABLE_BSID 0x23 /* BSID Unreachable */
/* Error Codes: 0x30-0x7F Message-specific Failure Codes */
#define ASNV_FAILURE_IND_UNAVAILABLE_CONTEXT 0x30 /* Requested Context Unavailable */
#define ASNV_FAILURE_IND_AUTHORIZATION 0x31 /* Authorization Failure */
#define ASNV_FAILURE_IND_REGISTRATION 0x32 /* Registration Failure */
#define ASNV_FAILURE_IND_NO_RESOURCE 0x33 /* No Resources */
#define ASNV_FAILURE_IND_REJECTION_OF_MS 0x34 /* Failure by rejection of MS */
#define ASNV_FAILURE_IND_AUTHENTICATOR_RELOC 0x35 /* Authenticator relocated */
#define ASNV_FAILURE_IND_PERIODIC_REPORT_RRM 0x36 /* Does not support periodic reporting of RRM messages */
#define ASNV_FAILURE_IND_LOCATION_UPDATE 0x37 /* Location Update Failure */
#define ASNV_FAILURE_IND_IDLE_MODE_AUTH 0x38 /* Idle Mode Authorization Failure */
#define ASNV_FAILURE_IND_UNSPPORTED_HO_TYPE 0x39 /* Target BS doesnt support this HO Type */
#define ASNV_FAILURE_IND_BS_INSUFFICIENT_AIR 0x3A /* Insufficient Target BS airlink resource */
#define ASNV_FAILURE_IND_BS_CPU_OVERLOAD 0x3B /* Target BS CPU overload */
#define ASNL_DEST_ID_IPV4 4
#define ASNL_DEST_ID_80216 6
#define ASNL_DEST_ID_IPV6 16
#define ASNL_DEST_ID_MAX ASNL_DEST_ID_IPV6
#define ASNL_SRC_ID_IPV4 4
#define ASNL_SRC_ID_80216 6
#define ASNL_SRC_ID_IPV6 16
#define ASNL_SRC_ID_MAX ASNL_SRC_ID_IPV6
#define ASNV_INITIAL_NETWORK_ENTRY 0X00000000
#define ASNV_HANDOFF 0X00000001
#define ASNV_IN_SERVICE_DATA_PATH_ESTABLISHMENT 0X00000002
#define ASNV_MS_NETWORK_EXIT 0X00000003
#define ASNV_IDLE_MODE_ENTRY 0X00000004
#define ASNV_IDLE_MODE_EXIT 0X00000005
#define ASNV_ANCHOR_DPF_RELOCATION 0X00000006
#define ASNV_CREATE_SERVICE_FLOW 0x0001
#define ASNV_ADMIT_SERVICE_FLOW 0x0002
#define ASNV_ACTIVATE_SERVICE_FLOW 0x0004
#define ASNV_MODIFY_SERVICE_FLOW 0x0008
#define ASNV_DELETE_SERVICE_FLOW 0x0010
#define ASNV_UPLINK 0x0000
#define ASNV_DOWNLINK 0x0001
#define ASNV_SERVING 0x00
#define ASNV_TARGET 0x01
#define ASNV_SUCCESSFULLY_CREATED 0X0000
#define ASNV_REQUEST_DENIED_NO_RESOURCES 0X0001
#define ASNV_REQUEST_DENIED_DUE_TO_POLICY 0X0002
#define ASNV_REQUEST_DENIED_DUE_TO_REQUESTS_FOR_OTHER_FLOWS_FAILED 0X0003
#define ASNV_REQUEST_FAILED_UNSPECIFIED_REASON 0X0004
#define ASNV_REQUEST_DENIED_DUE_TO_MS_REASON 0X0005
#define BUILDER_TRACE() d_trace(1, "Builder: %s()\n", __func__)
#define PARSER_TRACE() d_trace(1, "Parser: %s()\n", __func__)
#if 1
#define TLV_TRACE(__t, __l, __v) \
d_trace_hex(1, __v, __l)
#define PAYLOAD_TRACE(__b, __l) \
d_trace(1, "Built payload: "); \
d_trace_hex(1, __b, __l);
#else
#define TLV_TRACE(__t, __l, __v)
#define PAYLOAD_TRACE(__b, __l)
#endif