/* (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 #include //#include #include #include #include "tcap_user.h" static struct { int mode_sender; struct tcap_transport_entity *tte; unsigned int begin_rcvd:1; uint32_t dialg_id; } test_state; static int send_cont_end(uint32_t dialg_id, struct tcap_obj_ident *app_ctx, struct tcap_user_info *user_info, int end) { struct tcap_prim_buf tcpb; struct tcap_dialg_ind *tcdi = &tcpb.dialg; memset(&tcpb, 0, sizeof(tcpb)); if (end) tcpb.prim = TCAP_PR_TC_END; else tcpb.prim = TCAP_PR_TC_CONTINUE; tcdi->dialg_id = dialg_id; if (app_ctx) { memcpy(&tcdi->app_ctx_name, app_ctx, sizeof(tcdi->app_ctx_name)); tcdi->app_ctx_present = 1; } if (user_info) { memcpy(&tcdi->user_info, user_info, sizeof(tcdi->user_info)); tcdi->user_info_present = 1; } return tcap_user_req(&tcpb); } /* UpdateGprsLocationArg */ static struct tcap_obj_ident gprsLocationUpdateContext_v3 = { .arc = { 0, 4, 0, 0, 1, 0, 32, 3 }, .num_arcs = 8, }; static uint8_t gprs_loc_upd_param[] = { 0x30, 0x1d, 0x04, 0x0f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x31, 0x32, 0x33, 0x34, 0x35, 0x04, 0x01, 0x31, 0x04, 0x07, 0x31, 0x2e, 0x32, 0x2e, 0x33, 0x2e, 0x34 }; static int send_comp_req(enum tcap_primitive prim, uint32_t dialg_id, int8_t invoke_id, uint8_t *param, uint32_t param_len) { struct tcap_prim_buf tcpb; struct tcap_component_ind *tcci = &tcpb.comp; memset(&tcpb, 0, sizeof(tcpb)); tcpb.prim = prim; tcci->dialg_id = dialg_id; tcci->invoke_id = invoke_id; tcci->linked_id = NULL; tcci->operation.local = 1; tcci->timeout_secs = 10; tcci->op_class = 1; 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(&tcpb); } static int send_begin(uint32_t dialg_id, struct tcap_obj_ident *app_ctx) { struct tcap_prim_buf tcpb; struct tcap_dialg_ind *tcdi = &tcpb.dialg; memset(&tcpb, 0, sizeof(tcpb)); tcpb.prim = TCAP_PR_TC_BEGIN; tcdi->dialg_id = dialg_id; if (app_ctx) { memcpy(&tcdi->app_ctx_name, app_ctx, sizeof(tcdi->app_ctx_name)); tcdi->app_ctx_present = 1; } tcdi->transp_ent = test_state.tte; return tcap_user_req(&tcpb); } static int tcap_user_ind_dialg(enum tcap_primitive prim, struct tcap_dialg_ind *tcdi) { printf("-> USER_IND_DIALG(%s): ", tcap_prim_name(prim)); switch (prim) { case TCAP_PR_TC_BEGIN: test_state.begin_rcvd = 1; test_state.dialg_id = tcdi->dialg_id; printf("dialg_id=0x%08x ", tcdi->dialg_id); break; default: break; } printf("\n"); return 0; } static int tcap_user_ind_comp(enum tcap_primitive prim, struct tcap_component_ind *tcci) { printf("-> USER_IND_COMP(%s)\n", tcap_prim_name(prim)); if (!test_state.begin_rcvd) return -1; switch (prim) { case TCAP_PR_TC_INVOKE: /* actually process the invoke */ send_comp_req(TCAP_PR_TC_RESULT_L, test_state.dialg_id, tcci->invoke_id, NULL, 0); if (tcci->last_component) send_cont_end(test_state.dialg_id, &gprsLocationUpdateContext_v3, NULL, 1); break; default: break; } return 0; } int tcap_user_ind_cb(struct tcap_prim_buf *tcpb) { int rc; if (tcpb->prim > _TCAP_PR_COMP_BASE) rc = tcap_user_ind_comp(tcpb->prim, &tcpb->comp); else rc = tcap_user_ind_dialg(tcpb->prim, &tcpb->dialg); talloc_free(tcpb); } static void signal_handler(int signal) { switch (signal) { case SIGINT: talloc_report_full(NULL, stderr); exit(0); break; case SIGSEGV: case SIGABRT: talloc_report_full(NULL, stderr); break; default: break; } } int main(int argc, char **argv) { struct sockaddr_storage ss; struct sockaddr_in *sin = (struct sockaddr_in *)&ss; if (argc > 1) test_state.mode_sender = 1; talloc_enable_leak_report_full(); signal(SIGINT, &signal_handler); //signal(SIGSEGV, &signal_handler); //signal(SIGABRT, &signal_handler); ss.ss_family = AF_INET; sin->sin_addr.s_addr = INADDR_ANY; if (test_state.mode_sender) sin->sin_port = htons(4242); else sin->sin_port = htons(4243); test_state.tte = tcap_transp_udp_create(&ss); if (!test_state.tte) { fprintf(stderr, "Cannot create UDP socket\n"); exit(1); } /* make sure we sent messages to ourselves */ inet_aton("127.0.0.1", &sin->sin_addr); if (!test_state.mode_sender) sin->sin_port = htons(4242); else sin->sin_port = htons(4243); memcpy(&test_state.tte->remote_addr, &ss, sizeof(test_state.tte->remote_addr)); if (test_state.mode_sender) { /* sender mode, send primitives */ send_comp_req(TCAP_PR_TC_INVOKE, 0x1234, 0, gprs_loc_upd_param, sizeof(gprs_loc_upd_param)); send_comp_req(TCAP_PR_TC_INVOKE, 0x1234, 1, NULL, 0); send_comp_req(TCAP_PR_TC_INVOKE, 0x1234, -1, NULL, 0); send_begin(0x1234, &gprsLocationUpdateContext_v3); } while (1) { bsc_select_main(0); } }