diff --git a/src/csl_dha.c b/src/csl_dha.c index c59226d..0b2db68 100644 --- a/src/csl_dha.c +++ b/src/csl_dha.c @@ -1,6 +1,7 @@ /* ITU-T Q.77x TCAP / CSL - Component Sub-Layer */ #include +#include #include #include @@ -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 */ diff --git a/src/scXp.c b/src/scXp.c index 87cc82b..e658bbb 100644 --- a/src/scXp.c +++ b/src/scXp.c @@ -1,9 +1,16 @@ /* SCCP / SCTP+SUA interface */ +#include + +#include +#include + +#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 */ diff --git a/src/tcap.h b/src/tcap.h index 738e9b9..20d259e 100644 --- a/src/tcap.h +++ b/src/tcap.h @@ -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); diff --git a/src/tcap_test.c b/src/tcap_test.c index cbfe144..35d5965 100644 --- a/src/tcap_test.c +++ b/src/tcap_test.c @@ -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); } diff --git a/src/tsl_tco.c b/src/tsl_tco.c index 8fcc5ae..4bc2662 100644 --- a/src/tsl_tco.c +++ b/src/tsl_tco.c @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -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); } diff --git a/src/tsl_tsm.c b/src/tsl_tsm.c index 401cb23..4c38862 100644 --- a/src/tsl_tsm.c +++ b/src/tsl_tsm.c @@ -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);