Don't use stack-based libasn1c objects for component primitives
In order for the recursive free-ing of libasn1c data structures to work, we cannot have some of them stack-allocated.
This commit is contained in:
parent
a7c47009c9
commit
57058f3600
|
@ -71,6 +71,11 @@ static Parameter_t *gen_param(const void *ctx, uint8_t *param, uint32_t param_le
|
|||
};
|
||||
|
||||
/* TC-INVOKE.req (TCU -> CHA) */
|
||||
/*
|
||||
* linked_id not referenced after call, caller needs to free it
|
||||
* op not referenced after call, caller needs to free it
|
||||
* param not referenced after call, caller needs to free it
|
||||
*/
|
||||
int tcap_cha_tc_invoke_req(struct tcap_dialogue *td, uint8_t op_class, int8_t inv_id,
|
||||
int8_t *linked_id, struct OPERATION *op,
|
||||
uint8_t *param, uint32_t param_len, uint32_t timeout)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
@ -56,12 +57,6 @@ static int send_continue(uint32_t dialg_id, struct tcap_obj_ident *app_ctx, stru
|
|||
return tcap_user_req_dialg(TCAP_PR_TC_CONTINUE, &tcdi);
|
||||
}
|
||||
|
||||
static void tcap_gen_oper_local(struct OPERATION *op, uint32_t local_value)
|
||||
{
|
||||
op->present = OPERATION_PR_localValue;
|
||||
asn_long2INTEGER(&op->choice.localValue, local_value);
|
||||
}
|
||||
|
||||
/* UpdateGprsLocationArg */
|
||||
static struct tcap_obj_ident gprsLocationUpdateContext_v3 = {
|
||||
.arc = { 0, 4, 0, 0, 1, 0, 32, 3 },
|
||||
|
@ -82,12 +77,14 @@ static int send_invoke(uint32_t dialg_id, int8_t invoke_id, uint8_t *param, uint
|
|||
tcci.dialg_id = dialg_id;
|
||||
tcci.invoke_id = invoke_id;
|
||||
tcci.linked_id = NULL;
|
||||
tcap_gen_oper_local(&tcci.operation, 1);
|
||||
tcci.operation.local = 1;
|
||||
tcci.timeout_secs = 10;
|
||||
tcci.op_class = 1;
|
||||
|
||||
tcci.parameter.buf = param;
|
||||
tcci.parameter.size = param_len;
|
||||
if (param_len > sizeof(tcci.parameter.data))
|
||||
return -EINVAL;
|
||||
memcpy(&tcci.parameter.data, param, param_len);
|
||||
tcci.parameter.data_len = param_len;
|
||||
|
||||
return tcap_user_req_comp(TCAP_PR_TC_INVOKE, &tcci);
|
||||
}
|
||||
|
|
|
@ -95,12 +95,22 @@ struct tcap_dialg_ind {
|
|||
|
||||
/* metadata associated with a component indication primitive */
|
||||
struct tcap_component_ind {
|
||||
/* Dummy list head structure for the user. libosmo-tcap doesn't use it */
|
||||
struct llist_head list;
|
||||
/* public */
|
||||
uint32_t dialg_id; /* Dialogue ID */
|
||||
int8_t invoke_id; /* Invoke ID */
|
||||
int8_t *linked_id; /* Linked ID */
|
||||
struct OPERATION operation; /* Operation Code */
|
||||
Parameter_t parameter; /* ANY_t */
|
||||
struct {
|
||||
int is_global:1; /* is it global (1) or local (0) */
|
||||
union {
|
||||
/* Global Operation (OID) */
|
||||
struct tcap_obj_ident global;
|
||||
/* Local Operation */
|
||||
long local;
|
||||
};
|
||||
} operation;
|
||||
struct tcap_user_info parameter;
|
||||
int last_component; /* is this the last component in the msg? */
|
||||
uint32_t timeout_secs; /* Timeout in seconds */
|
||||
uint32_t error;
|
||||
|
|
122
src/tcu.c
122
src/tcu.c
|
@ -1,4 +1,4 @@
|
|||
/* TC-User */
|
||||
/* TC-User API / Interface between TCAP protocol manager and User Application */
|
||||
|
||||
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010 by On-Waves
|
||||
|
@ -27,18 +27,12 @@
|
|||
#include <osmocore/talloc.h>
|
||||
|
||||
#include <osmocom/tcap/Parameter.h>
|
||||
#include <osmocom/tcap/OPERATION.h>
|
||||
|
||||
#include "tcap.h"
|
||||
#include "tcap_user.h"
|
||||
|
||||
void *tcap_dialg_ind_ctx;
|
||||
|
||||
static struct tcap_dialg_ind *tcap_dialg_ind_alloc(void)
|
||||
{
|
||||
struct tcap_dialg_ind *tcdi = talloc_zero(tcap_dialg_ind_ctx,
|
||||
struct tcap_dialg_ind);
|
||||
return tcdi;
|
||||
}
|
||||
void *tcap_ind_ctx;
|
||||
|
||||
static const struct value_string tcap_prim_names[] = {
|
||||
/* dialogue handling */
|
||||
|
@ -67,9 +61,16 @@ LIB_EXPORTED const char *tcap_prim_name(enum tcap_primitive prim)
|
|||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Component Primitives */
|
||||
/* Dialogue Primitives */
|
||||
/***********************************************************************/
|
||||
|
||||
static struct tcap_dialg_ind *tcap_dialg_ind_alloc(void)
|
||||
{
|
||||
struct tcap_dialg_ind *tcdi = talloc_zero(tcap_ind_ctx,
|
||||
struct tcap_dialg_ind);
|
||||
return tcdi;
|
||||
}
|
||||
|
||||
/* fill the application context and user information part of 'tcap_dialg_ind' */
|
||||
static int fill_tcap_dialg_ind(struct tcap_dialg_ind *tcdi,
|
||||
OBJECT_IDENTIFIER_t *app_ctx_name,
|
||||
|
@ -226,22 +227,58 @@ LIB_EXPORTED int tcap_user_req_dialg(enum tcap_primitive prim, struct tcap_dialg
|
|||
/* Component Primitives */
|
||||
/***********************************************************************/
|
||||
|
||||
static struct tcap_component_ind *tcap_comp_ind_alloc(void)
|
||||
{
|
||||
struct tcap_component_ind *tcci = talloc_zero(tcap_ind_ctx,
|
||||
struct tcap_component_ind);
|
||||
return tcci;
|
||||
}
|
||||
|
||||
static int _tcu_comp_ind(enum tcap_primitive prim, struct tcap_invocation *ti, struct OPERATION *oper,
|
||||
Parameter_t *param, int last)
|
||||
{
|
||||
struct tcap_component_ind tcci;
|
||||
struct tcap_component_ind *tcci = tcap_comp_ind_alloc();
|
||||
int rc;
|
||||
|
||||
memset(&tcci, 0, sizeof(tcci));
|
||||
tcci.dialg_id = ti->dialogue->dialogue_id;
|
||||
tcci.invoke_id = ti->invoke_id;
|
||||
tcci->dialg_id = ti->dialogue->dialogue_id;
|
||||
tcci->invoke_id = ti->invoke_id;
|
||||
if (ti->linked_id) {
|
||||
tcci._linked_id = ti->_linked_id;
|
||||
tcci.linked_id = &tcci._linked_id;
|
||||
tcci->_linked_id = ti->_linked_id;
|
||||
tcci->linked_id = &tcci->_linked_id;
|
||||
}
|
||||
memcpy(&tcci.operation, oper, sizeof(tcci.operation));
|
||||
tcci.last_component = last;
|
||||
if (oper && oper->present != OPERATION_PR_NOTHING) {
|
||||
switch (oper->present) {
|
||||
case OPERATION_PR_localValue:
|
||||
rc = asn_INTEGER2long(&oper->choice.localValue, &tcci->operation.local);
|
||||
if (rc < 0)
|
||||
goto out_free;
|
||||
break;
|
||||
case OPERATION_PR_globalValue:
|
||||
rc = OBJECT_IDENTIFIER_get_arcs(&oper->choice.globalValue,
|
||||
&tcci->operation.global.arc,
|
||||
sizeof(tcci->operation.global.arc[0]),
|
||||
ARRAY_SIZE(tcci->operation.global.arc));
|
||||
if (rc < 0)
|
||||
goto out_free;
|
||||
tcci->operation.global.num_arcs = rc;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (param) {
|
||||
if (param->size > sizeof(tcci->parameter.data))
|
||||
goto out_free;
|
||||
memcpy(tcci->parameter.data, param->buf, param->size);
|
||||
tcci->parameter.data_len = param->size;
|
||||
}
|
||||
tcci->last_component = last;
|
||||
|
||||
return tcap_user_ind_comp(prim, &tcci);
|
||||
return tcap_user_ind_comp(prim, tcci);
|
||||
|
||||
out_free:
|
||||
talloc_free(tcci);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Table 10 / Q.771 : TC-INVOKE.ind */
|
||||
|
@ -274,9 +311,32 @@ int tcap_tcu_result_nl_ind(struct tcap_invocation *ti, struct OPERATION *oper, P
|
|||
return _tcu_comp_ind(TCAP_PR_TC_RESULT_NL, ti, oper, param, last);
|
||||
}
|
||||
|
||||
static OPERATION_t *generate_op(struct tcap_dialogue *td, struct tcap_component_ind *tcci)
|
||||
{
|
||||
OPERATION_t *op;
|
||||
|
||||
op = talloc_zero(td, OPERATION_t);
|
||||
if (!op)
|
||||
return NULL;
|
||||
|
||||
if (tcci->operation.is_global) {
|
||||
op->present = OPERATION_PR_globalValue;
|
||||
OBJECT_IDENTIFIER_set_arcs(&op->choice.globalValue,
|
||||
tcci->operation.global.arc,
|
||||
sizeof(tcci->operation.global.arc[0]),
|
||||
tcci->operation.global.num_arcs);
|
||||
} else {
|
||||
op->present = OPERATION_PR_localValue;
|
||||
asn_long2INTEGER(&op->choice.localValue, tcci->operation.local);
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
LIB_EXPORTED int tcap_user_req_comp(enum tcap_primitive prim, struct tcap_component_ind *tcci)
|
||||
{
|
||||
struct tcap_dialogue *td;
|
||||
OPERATION_t *op = NULL;
|
||||
int rc = 0;
|
||||
|
||||
fprintf(stdout, "<- USER_REQ_COMP(%s)\n", tcap_prim_name(prim));
|
||||
|
@ -297,23 +357,31 @@ LIB_EXPORTED int tcap_user_req_comp(enum tcap_primitive prim, struct tcap_compon
|
|||
/* Actually dispatch the primitive */
|
||||
switch (prim) {
|
||||
case TCAP_PR_TC_INVOKE:
|
||||
rc = tcap_cha_tc_invoke_req(td, tcci->op_class, tcci->invoke_id, tcci->linked_id, &tcci->operation,
|
||||
tcci->parameter.buf, tcci->parameter.size, tcci->timeout_secs);
|
||||
op = generate_op(td, tcci);
|
||||
rc = tcap_cha_tc_invoke_req(td, tcci->op_class, tcci->invoke_id,
|
||||
tcci->linked_id, op, tcci->parameter.data,
|
||||
tcci->parameter.data_len, tcci->timeout_secs);
|
||||
break;
|
||||
case TCAP_PR_TC_RESULT_L:
|
||||
rc = tcap_cha_tc_result_req(td, tcci->invoke_id, 1, &tcci->operation, &tcci->parameter.buf,
|
||||
tcci->parameter.buf);
|
||||
op = generate_op(td, tcci);
|
||||
rc = tcap_cha_tc_result_req(td, tcci->invoke_id, 1, op,
|
||||
&tcci->parameter.data, tcci->parameter.data_len);
|
||||
break;
|
||||
case TCAP_PR_TC_RESULT_NL:
|
||||
rc = tcap_cha_tc_result_req(td, tcci->invoke_id, 0, &tcci->operation, tcci->parameter.buf,
|
||||
tcci->parameter.buf);
|
||||
op = generate_op(td, tcci);
|
||||
rc = tcap_cha_tc_result_req(td, tcci->invoke_id, 0, op,
|
||||
tcci->parameter.data, tcci->parameter.data_len);
|
||||
break;
|
||||
case TCAP_PR_TC_U_ERROR:
|
||||
case TCAP_PR_TC_U_REJECT:
|
||||
case TCAP_PR_TC_CANCEL:
|
||||
case TCAP_PR_TC_TIMER_RESET:
|
||||
default:
|
||||
fprintf(stderr, "unsupported dialogue primitive %s\n", tcap_prim_name(prim));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
talloc_free(op);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue