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:
Harald Welte 2010-07-19 18:33:53 +02:00
parent a7c47009c9
commit 57058f3600
4 changed files with 118 additions and 38 deletions

View File

@ -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)

View File

@ -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);
}

View File

@ -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
View File

@ -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;
}