Actually do the DER/BER encode and hexdump it

Also, implement the CONTINUE and END transactions.
This commit is contained in:
Harald Welte 2010-07-16 20:35:20 +02:00
parent c130f62cbc
commit 096b22cfff
6 changed files with 146 additions and 47 deletions

View File

@ -1,6 +1,7 @@
/* ITU-T Q.77x TCAP / CSL - Component Sub-Layer */
#include <errno.h>
#include <netinet/in.h>
#include <osmocore/talloc.h>
#include <osmocore/msgb.h>
@ -45,7 +46,8 @@ int tcap_csl_tc_begin_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx
struct TCMessage tcm;
struct ComponentPortion cp;
ExternalPDU_t ext;
DialoguePDU_t *dial = NULL;
DialoguePDU_t dial;
ANY_t any;
struct tcap_invocation *ti;
uint32_t trans_id, comp_count = 0;
int rc;
@ -56,11 +58,9 @@ int tcap_csl_tc_begin_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx
if (app_ctx) {
AARQ_apdu_t *aarq;
dial = calloc(1, sizeof(*dial));
memset(dial, 0, sizeof(*dial));
dial->present = DialoguePDU_PR_dialogueRequest;
dial.present = DialoguePDU_PR_dialogueRequest;
aarq = &dial->choice.dialogueRequest;
aarq = &dial.choice.dialogueRequest;
if (user_info)
aarq->user_information = user_info;
/* Set Application context mode */
@ -69,9 +69,10 @@ int tcap_csl_tc_begin_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx
aarq->protocol_version = &dial_version1;
/* Build AARQ apdu */
fprintf(stdout, "\nDialogue portion:\n");
xer_fprint(stdout, &asn_DEF_DialoguePDU, dial);
ANY_fromType(&ext.dialog, &asn_DEF_DialoguePDU, dial);
tcm.choice.begin.dialoguePortion = ANY_new_fromType(&asn_DEF_ExternalPDU, &ext);
xer_fprint(stdout, &asn_DEF_DialoguePDU, &dial);
ANY_fromType(&ext.dialog, &asn_DEF_DialoguePDU, &dial);
ANY_fromType(&any, &asn_DEF_ExternalPDU, &ext);
tcm.choice.begin.dialoguePortion = (OCTET_STRING_t *) &any;
}
/* Request components to CHA */
/* Process components */
@ -93,7 +94,7 @@ int tcap_csl_tc_begin_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx
(const char *) &trans_id, sizeof(trans_id));
/* TR-BEGIN-REQ to TSL */
rc = tcap_tco_tr_begin_req(&td->trans, &tcm, NULL);
rc = tcap_tco_tr_begin_req(&td->trans, &tcm);
td->trans.state = TCAP_TS_INIT_SENT;
@ -136,7 +137,7 @@ int tcap_csl_tr_begin_ind(struct tcap_transaction *tt, struct TCMessage *tcmsg,
/* Build ABORT apdu */
/* Discard components */
/* TR-U-ABPRT.req to TSL */
rc = tcap_tco_tr_u_abort_req(tt, tcmsg, msg);
rc = tcap_tco_tr_u_abort_req(tt, tcmsg);
/* Dalogue terminated to CHA */
tcap_cha_dialg_term(td);
}
@ -160,28 +161,72 @@ int tcap_csl_tr_begin_ind(struct tcap_transaction *tt, struct TCMessage *tcmsg,
tt->state = TCAP_TS_INIT_RECV;
}
static int gen_ext_AARE(struct DialoguePDU *dial, ANY_t *any, ExternalPDU_t *ext,
OBJECT_IDENTIFIER_t *app_ctx, struct user_information *user_info)
{
AARE_apdu_t *aare;
int rc;
memset(&dial, 0, sizeof(dial));
dial->present = DialoguePDU_PR_dialogueResponse;
aare = &dial->choice.dialogueResponse;
/* Set protocol version 1 */
aare->protocol_version = &dial_version1;
/* Build AARE-apdu (accepted) */
memcpy(&aare->application_context_name, app_ctx, sizeof(aare->application_context_name));
asn_long2INTEGER(&aare->result, Associate_result_accepted);
aare->user_information = user_info;
/* Link Dialogue into External PDU */
rc = ANY_fromType(&ext->dialog, &asn_DEF_DialoguePDU, &dial);
if (rc < 0)
return rc;
/* Link External PDU into Dialogue Portion */
rc = ANY_fromType(any, &asn_DEF_ExternalPDU, &ext);
if (rc < 0)
return rc;
return 0;
}
/* TC-CONTINUE.req from TCU */
int tcap_csl_tc_cont_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx, struct user_information *user_info)
{
struct TCMessage tcm;
struct ComponentPortion cp;
ExternalPDU_t ext;
DialoguePDU_t dial;
ANY_t any;
uint32_t trans_id, comp_count = 0;
int rc = 0;
memset(&tcm, 0, sizeof(tcm));
tcm.present = TCMessage_PR_continue;
switch (td->trans.state) {
case TCAP_TS_INIT_RECV:
if (app_ctx && user_info) {
/* Set protocol version 1 */
/* Build AARE-apdu (accepted) */
gen_ext_AARE(&dial, &any, &ext, app_ctx, user_info);
fprintf(stdout, "\nTC-CONTINUE.req Dialogue portion:\n");
xer_fprintf(stdout, &asn_DEF_DialoguePDU, &dial);
tcm.choice.Continue.dialoguePortion = (OCTET_STRING_t *) &any;
}
break;
case TCAP_TS_ACTIVE:
break;
default:
fprintf(stderr, "TC-CONTNUE.req in invalid state\n");
return -EINVAL;
}
/* Request components to CHA */
/* Porcess components */
/* FIXME: Request components to CHA */
/* FIXME: Process components */
/* Assemble TSL user data */
if (comp_count)
tcm.choice.Continue.components = &cp;
/* TR-CONTINUE to TSL */
//rc = tcap_tco_tr_continue_req();
rc = tcap_tco_tr_continue_req(&td->trans, &tcm);
td->trans.state = TCAP_TS_ACTIVE;
return rc;
@ -190,39 +235,51 @@ int tcap_csl_tc_cont_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx,
/* TC-END.req from TCU */
int tcap_csl_tc_end_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx, struct user_information *user_info, int prearranged)
{
struct TCMessage tcm;
struct ComponentPortion cp;
ExternalPDU_t ext;
DialoguePDU_t dial;
ANY_t any;
uint32_t trans_id, comp_count = 0;
int rc = 0;
memset(&tcm, 0, sizeof(tcm));
tcm.present = TCMessage_PR_end;
switch (td->trans.state) {
case TCAP_TS_INIT_RECV:
case TCAP_TS_ACTIVE:
break;
case TCAP_TS_INIT_SENT:
/* TR-END.req to TSL */
//rc = tcap_tco_tr_end_req(&td->trans, tcmsg, msg);
rc = tcap_tco_tr_end_req(&td->trans, &tcm);
/* Dialogue terminated to CHA */
tcap_cha_dialg_term(td);
return 0;
return rc;
default:
fprintf(stderr, "TC-END.req in invalid state\n");
return -EINVAL;
}
if (prearranged) {
/* TR-END.req to TSL */
//rc = tcap_tco_tr_end_req(&td->trans, tcmsg, msg);
rc = tcap_tco_tr_end_req(&td->trans, &tcm);
/* Dialogue terminated to CHA */
tcap_cha_dialg_term(td);
/* Free Dialogue ID */
return 0;
return rc;
}
if (td->trans.state == TCAP_TS_INIT_RECV && (app_ctx && user_info)) {
/* Set protocol version 1 */
/* Build AARE apdu (accepted) */
gen_ext_AARE(&dial, &any, &ext, app_ctx, user_info);
fprintf(stdout, "\nTC-END.req Dialogue portion:\n");
xer_fprintf(stdout, &asn_DEF_DialoguePDU, &dial);
tcm.choice.end.dialoguePortion = (OCTET_STRING_t *) &any;
}
/* Request component to CHA */
/* Process components */
/* Assemble TLS user data */
/* TR-END.req to TSL */
//rc = tcap_tco_tr_end_req();
rc = tcap_tco_tr_end_req(&td->trans, &tcm);
/* Dialogue terminated to CHA */
tcap_cha_dialg_term(td);
/* Free Dialogue ID */
@ -365,7 +422,7 @@ err_discard:
rc = tcap_tcu_abort_ind(td, app_ctx_name, user_info);
/* Build ABRT apdu */
/* TR-U-ABORT.req to TSL */
rc = tcap_tco_tr_u_abort_req(tt, tcmsg, msg);
rc = tcap_tco_tr_u_abort_req(tt, tcmsg);
/* Dialogue terminated to CHA */
tcap_cha_dialg_term(td);
/* Free Dialogue ID */

View File

@ -1,9 +1,16 @@
/* SCCP / SCTP+SUA interface */
#include <stdio.h>
#include <osmocore/logging.h>
#include <osmocore/msgb.h>
#include "tcap_user.h"
/* Called by TCAP stack if it wants to request transmission of UNITDATA */
int tcap_scXp_n_unitdata_req(struct scxp_entity *se, struct msgb *msg)
{
printf("N-UNITDATA.req(%s)\n", hexdump(msg->data, msg->len));
}
/* prototype of what we need to call in case of incoming UNITDATA */

View File

@ -171,19 +171,19 @@ int tcap_csl_tr_p_abort_ind(struct tcap_transaction *tt);
int tcap_tco_n_unitdata_ind(struct scxp_entity *se, struct msgb *msg);
int tcap_tco_n_notice_ind(struct scxp_entity *se);
int tcap_tco_tsm_stopped_ind(struct tcap_transaction *tt);
int tcap_tco_tr_uni_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tco_tr_begin_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tco_tr_continue_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tco_tr_end_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tco_tr_u_abort_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tco_tr_uni_req(struct tcap_transaction *tt, struct TCMessage *tcmsg);
int tcap_tco_tr_begin_req(struct tcap_transaction *tt, struct TCMessage *tcmsg);
int tcap_tco_tr_continue_req(struct tcap_transaction *tt, struct TCMessage *tcmsg);
int tcap_tco_tr_end_req(struct tcap_transaction *tt, struct TCMessage *tcmsg);
int tcap_tco_tr_u_abort_req(struct tcap_transaction *tt, struct TCMessage *tcmsg);
/* TSL TSM */
int tcap_tsm_begin_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg);
int tcap_tsm_continue_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg);
int tcap_tsm_end_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg);
int tcap_tsm_abort_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg);
int tcap_tsm_begin_rcvd(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tsm_begin_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tsm_continue_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tsm_end_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tsm_abort_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tsm_continue_rcvd(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tsm_end_rcvd(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);
int tcap_tsm_abort_rcvd(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg);

View File

@ -25,10 +25,13 @@ static void tcap_gen_oper_local(struct OPERATION *op, uint32_t local_value)
asn_long2INTEGER(&op->choice.localValue, local_value);
}
static uint8_t invoke_parameter[8];
static int send_invoke(int8_t invoke_id)
{
struct tcap_component_ind tcci;
memset(&tcci, 0, sizeof(tcci));
tcci.dialg_id = 1234;
tcci.invoke_id = invoke_id;
@ -36,6 +39,10 @@ static int send_invoke(int8_t invoke_id)
tcap_gen_oper_local(&tcci.operation, 1);
tcci.timeout_secs = 10;
tcci.op_class = 1;
memset(invoke_parameter, invoke_id, sizeof(invoke_parameter));
tcci.parameter.buf = invoke_parameter;
tcci.parameter.size = sizeof(invoke_parameter);
return tcap_user_req_comp(TCAP_PR_TC_INVOKE, &tcci);
}

View File

@ -2,6 +2,7 @@
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <osmocore/msgb.h>
#include <osmocom/tcap/TCMessage.h>
@ -94,37 +95,37 @@ int tcap_tco_tsm_stopped_ind(struct tcap_transaction *tt)
}
/* TR-UNI.req from CSL */
int tcap_tco_tr_uni_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
int tcap_tco_tr_uni_req(struct tcap_transaction *tt, struct TCMessage *tcmsg)
{
/* FIXME: Assemble TR-portion of UNI message */
/* FIXME: N-UNITDATA.req to SCCP/SUA */
}
/* TR-BEGIN.req from CSL */
int tcap_tco_tr_begin_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
int tcap_tco_tr_begin_req(struct tcap_transaction *tt, struct TCMessage *tcmsg)
{
/* hand-off to TSM */
/* generate BEGIN transaction to TSM */
return tcap_tsm_begin_trans(tt, tcmsg, msg);
return tcap_tsm_begin_trans(tt, tcmsg);
}
/* TR-CONTINUE.req from CSL */
int tcap_tco_tr_continue_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
int tcap_tco_tr_continue_req(struct tcap_transaction *tt, struct TCMessage *tcmsg)
{
/* generate CONTINUE transaction to TSM */
return tcap_tsm_continue_trans(tt, tcmsg, msg);
return tcap_tsm_continue_trans(tt, tcmsg);
}
/* TR-END.req from CSL */
int tcap_tco_tr_end_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
int tcap_tco_tr_end_req(struct tcap_transaction *tt, struct TCMessage *tcmsg)
{
/* generate END transaction to TSM */
return tcap_tsm_end_trans(tt, tcmsg, msg);
return tcap_tsm_end_trans(tt, tcmsg);
}
/* TR-U-ABORT.req from CSL */
int tcap_tco_tr_u_abort_req(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
int tcap_tco_tr_u_abort_req(struct tcap_transaction *tt, struct TCMessage *tcmsg)
{
/* generate ABORT transaction to TSM */
return tcap_tsm_abort_trans(tt, tcmsg, msg);
return tcap_tsm_abort_trans(tt, tcmsg);
}

View File

@ -8,6 +8,14 @@
#include "tcap.h"
#define TCAP_MSGB_ALLOC_SIZE 4096
#define TCAP_MSGB_HEADR_SIZE 128
static inline struct msgb *tcap_msgb_alloc(void)
{
return msgb_alloc_headroom(TCAP_MSGB_ALLOC_SIZE+TCAP_MSGB_HEADR_SIZE, TCAP_MSGB_HEADR_SIZE, "tcap");
}
/* BEGIN received from remote (TCO -> TSM) */
int tcap_tsm_begin_rcvd(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
{
@ -31,17 +39,29 @@ int tcap_tsm_begin_rcvd(struct tcap_transaction *tt, struct TCMessage *tcmsg, st
}
/* BEGIN Transaction (TCO -> TSM) */
int tcap_tsm_begin_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
int tcap_tsm_begin_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg)
{
struct tcap_dialogue *td = dialg_by_trans(tt);
struct msgb *msg;
asn_enc_rval_t ar;
int rc;
if (tt->state != TCAP_TS_IDLE)
return -EINVAL;
msg = tcap_msgb_alloc();
xer_fprint(stdout, &asn_DEF_TCMessage, tcmsg);
/* FIXME: Store Local Address */
/* FIXME: Assemble TR-portion of BEGIN message */
xer_fprint(stdout, &asn_DEF_TCMessage, tcmsg);
ar = der_encode_to_buffer(&asn_DEF_TCMessage, tcmsg, msg->data, msgb_tailroom(msg));
if (ar.encoded < 0) {
fprintf(stdout, "some error during encode\n");
return -EIO;
}
msgb_put(msg, ar.encoded);
/* Send N-UNITDATA.req to SCCP / SUA */
rc = tcap_scXp_n_unitdata_req(td->se, msg);
@ -51,10 +71,11 @@ int tcap_tsm_begin_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, s
}
/* CONTINUE Transaction (TCO -> TSM) */
int tcap_tsm_continue_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
int tcap_tsm_continue_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg)
{
struct tcap_dialogue *td = dialg_by_trans(tt);
enum tcap_transaction_state new_state;
struct msgb *msg;
int rc;
switch (tt->state) {
@ -69,6 +90,8 @@ int tcap_tsm_continue_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg
return -EINVAL;
}
msg = tcap_msgb_alloc();
/* FIXME: Assemble TR-portion of CONTINUE message */
/* Send N-UNITDATA.req to SCCP / SUA */
rc = tcap_scXp_n_unitdata_req(td->se, msg);
@ -79,9 +102,10 @@ int tcap_tsm_continue_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg
}
/* END transaction (TCO -> TSM) */
int tcap_tsm_end_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
int tcap_tsm_end_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg)
{
struct tcap_dialogue *td = dialg_by_trans(tt);
struct msgb *msg;
int rc;
switch (tt->state) {
@ -89,6 +113,7 @@ int tcap_tsm_end_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, str
case TCAP_TS_ACTIVE:
if (1 /* FIXME: !prearranged */) {
/* FIXME: Assemble TR-portion of END message */
msg = tcap_msgb_alloc();
/* Send N-UNITDATA.req to SCCP / SUA */
rc = tcap_scXp_n_unitdata_req(td->se, msg);
}
@ -108,14 +133,16 @@ int tcap_tsm_end_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, str
}
/* ABORT transaction (TCO -> TSM) */
int tcap_tsm_abort_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg, struct msgb *msg)
int tcap_tsm_abort_trans(struct tcap_transaction *tt, struct TCMessage *tcmsg)
{
struct tcap_dialogue *td = dialg_by_trans(tt);
struct msgb *msg;
int rc = 0;
switch (tt->state) {
case TCAP_TS_INIT_RECV:
case TCAP_TS_ACTIVE:
msg = tcap_msgb_alloc();
/* FIXME: Assemble TR-portion of ABORT message */
/* N-UNITDATA.req to SCCP / SUA */
rc = tcap_scXp_n_unitdata_req(td->se, msg);