231 lines
5.6 KiB
C
231 lines
5.6 KiB
C
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
|
|
* (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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
|
|
//#include <asn1/OBJECT_IDENTIFIER.h>
|
|
|
|
#include <osmocore/utils.h>
|
|
#include <osmocore/talloc.h>
|
|
|
|
#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);
|
|
}
|
|
}
|