/* TC-User */ /* (C) 2010 by Harald Welte * (C) 2010 by On-Waves * * All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "tcap.h" #include "tcap_user.h" static const struct value_string tcap_prim_names[] = { /* dialogue handling */ { TCAP_PR_TC_UNI, "TC-UNI" }, { TCAP_PR_TC_BEGIN, "TC-BEGIN" }, { TCAP_PR_TC_CONTINUE, "TC-CONTINUE" }, { TCAP_PR_TC_END, "TC-END" }, { TCAP_PR_TC_U_ABORT, "TC-U-ABORT" }, { TCAP_PR_TC_NOTICE, "TC-NOTICE" }, /* component handling */ { TCAP_PR_TC_INVOKE, "TC-INVOKE" }, { TCAP_PR_TC_RESULT_L, "TC-RESULT-L" }, { TCAP_PR_TC_RESULT_NL, "TC-RESULT-NL" }, { TCAP_PR_TC_U_ERROR, "TC-U-ERROR" }, { TCAP_PR_TC_U_REJECT, "TC-U-REJECT" }, { TCAP_PR_TC_CANCEL, "TC-CANCEL" }, { TCAP_PR_TC_L_REJECT, "TC-L-REJECT" }, { TCAP_PR_TC_R_REJECT, "TC-R-REJECT" }, { TCAP_PR_TC_P_ABORT, "TC-P-ABORT" }, { 0, NULL } }; LIB_EXPORTED const char *tcap_prim_name(enum tcap_primitive prim) { return get_value_string(tcap_prim_names, prim); } /* Table 10 / Q.771 : TC-INVOKE.ind */ int tcap_tcu_tc_invoke_ind(struct tcap_invocation *ti, struct OPERATION *oper, Parameter_t *param, int last) { struct tcap_component_ind tcci; memset(&tcci, 0, sizeof(tcci)); 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; } memcpy(&tcci.operation, oper, sizeof(tcci.operation)); tcci.last_component = last; return tcap_user_ind_comp(TCAP_PR_TC_INVOKE, &tcci); } /* TC-L-REJECT.ind */ int tcap_tcu_tc_l_rej_ind(struct tcap_invocation *ti, int8_t *invoke_id, uint32_t problem) { } /* TC-R-REJECT.ind */ int tcap_tcu_tc_r_rej_ind(struct tcap_invocation *ti, int8_t *invoke_id, uint32_t problem) { } /* TC-BEGIN.ind from DHA */ int tcap_tcu_begin_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info, int comp_present) { struct tcap_dialg_ind tcdi; memset(&tcdi, 0, sizeof(tcdi)); tcdi.dialg_id = td->dialogue_id; tcdi.app_ctx_name = app_ctx_name; tcdi.user_info = user_info; tcdi.components_present = comp_present; return tcap_user_ind_dialg(TCAP_PR_TC_BEGIN, &tcdi); } /* TC-UNI.ind from DHA */ int tcap_tcu_uni_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info, int comp_present) { } /* TC-CONT.ind from DHA */ int tcap_tcu_cont_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info, int comp_present) { struct tcap_dialg_ind tcdi; memset(&tcdi, 0, sizeof(tcdi)); tcdi.dialg_id = td->dialogue_id; tcdi.app_ctx_name; tcdi.user_info; tcdi.components_present = comp_present; return tcap_user_ind_dialg(TCAP_PR_TC_CONTINUE, &tcdi); } /* TC-END.ind from DHA */ int tcap_tcu_end_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info, int comp_present) { struct tcap_dialg_ind tcdi; memset(&tcdi, 0, sizeof(tcdi)); tcdi.dialg_id = td->dialogue_id; tcdi.app_ctx_name; tcdi.user_info; tcdi.components_present = comp_present; return tcap_user_ind_dialg(TCAP_PR_TC_END, &tcdi); } /* TC-ABORT.ind from DHA */ int tcap_tcu_abort_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info) { } /* TC-NOTICE.ind from DHA */ int tcap_tcu_notice_ind(struct tcap_dialogue *td, uint32_t cause) { } /* TC-RESULT-L.ind from ISM */ int tcap_tcu_result_l_ind() { } /* TC-RESULT-NL.ind from ISM */ int tcap_tcu_result_nl_ind() { } LIB_EXPORTED int tcap_user_req_comp(enum tcap_primitive prim, struct tcap_component_ind *tcci) { struct tcap_dialogue *td; int rc = 0; /* Resolve (or allocate) the dialogue/transaction state */ td = tcap_dialg_by_dialg_id(tcci->dialg_id); if (!td) { switch (prim) { case TCAP_PR_TC_INVOKE: td = tcap_dialg_alloc(tcci->dialg_id); td->trans.tid_local = tcap_trans_id_alloc(); break; default: return -EINVAL; } } /* 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); 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); 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); break; default: fprintf(stderr, "unsupported dialogue primitive %s\n", tcap_prim_name(prim)); return -EINVAL; } return rc; } LIB_EXPORTED int tcap_user_req_dialg(enum tcap_primitive prim, struct tcap_dialg_ind *tcdi) { struct tcap_dialogue *td; int rc = 0; /* Resolve (or allocate) the dialogue/transaction state */ td = tcap_dialg_by_dialg_id(tcdi->dialg_id); if (!td) { switch (prim) { case TCAP_PR_TC_BEGIN: td = tcap_dialg_alloc(tcdi->dialg_id); if (!td) return -EINVAL; break; default: return -EINVAL; } } switch (prim) { case TCAP_PR_TC_BEGIN: td->transp_ent = tcdi->transp_ent; rc = tcap_csl_tc_begin_req(td, tcdi->app_ctx_name, tcdi->user_info); break; case TCAP_PR_TC_CONTINUE: fprintf(stdout, "TC-CONTINUE.req\n"); rc = tcap_csl_tc_cont_req(td, tcdi->app_ctx_name, tcdi->user_info); break; case TCAP_PR_TC_END: rc = tcap_csl_tc_end_req(td, tcdi->app_ctx_name, tcdi->user_info, tcdi->prearranged_end); break; default: fprintf(stderr, "unsupported component primitive %s\n", tcap_prim_name(prim)); return -EINVAL; } return rc; }