This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
tango-tsg-master/src/tsg_gtp_signaling.cpp
2023-04-03 08:30:49 +00:00

268 lines
6.0 KiB
C++

#include <stdio.h>
#include <string.h>
#include <MESA/stream.h>
#include <MESA/MESA_prof_load.h>
#include <MESA/MESA_handle_logger.h>
#include "tsg_rule_internal.h"
#include "tsg_gtp_signaling.h"
MESA_htable_handle g_gtp_signaling_hash_handle=NULL;
enum SIGNALING_ORIGIN
{
SIGNALING_ORIGIN_NO=0,
SIGNALING_ORIGIN_HASH=1,
SIGNALING_ORIGIN_REDIS=2,
};
static int is_gtp_tunnel(const struct streaminfo *a_stream)
{
int ret=0;
unsigned short is_tunnel=0;
int size=sizeof(unsigned short);
ret=MESA_get_stream_opt(a_stream, MSO_STREAM_TUNNEL_TYPE, (void *)&is_tunnel, &size);
if(ret>=0 && is_tunnel==STREAM_TUNNEL_GPRS_TUNNEL)
{
return 1;
}
return 0;
}
static int get_gtp_teid(const struct streaminfo *a_stream, unsigned int *uplink, unsigned int *downlink)
{
const struct streaminfo *p=a_stream;
while(p)
{
if(p->addr.addrtype==ADDR_TYPE_GPRS_TUNNEL)
{
*uplink=ntohl(p->addr.gtp->teid_c2s);
*downlink=ntohl(p->addr.gtp->teid_s2c);
return 1;
}
p=p->pfather;
}
return 0;
}
static int copy_one_field(char **dst, char *src, int src_len)
{
if(src!=NULL && src_len>0)
{
*dst=(char *)calloc(1, src_len+1);
memcpy(*dst, src, src_len);
return 1;
}
return 0;
}
static long copy_user_info(void *data, const uchar *key, uint size, void *user_arg)
{
int num=0;
struct gtp_signaling_field *signal=(struct gtp_signaling_field *)data;
struct umts_user_info *user_info=(struct umts_user_info *)user_arg;
if(signal!=NULL)
{
num+=copy_one_field(&(user_info->apn), (char *)(signal->ie_unit[GTP_FIELD_APN].value), signal->ie_unit[GTP_FIELD_APN].len);
num+=copy_one_field(&(user_info->imsi), (char *)(signal->ie_unit[GTP_FIELD_IMSI].value), signal->ie_unit[GTP_FIELD_IMSI].len);
num+=copy_one_field(&(user_info->imei), (char *)(signal->ie_unit[GTP_FIELD_IMEI].value), signal->ie_unit[GTP_FIELD_IMEI].len);
num+=copy_one_field(&(user_info->msisdn), (char *)(signal->ie_unit[GTP_FIELD_MSISDN].value), signal->ie_unit[GTP_FIELD_MSISDN].len);
}
return num;
}
unsigned int gtp_c_key2index(const MESA_htable_handle table, const uchar * key, uint size)
{
if(size==sizeof(unsigned int))
{
return *(unsigned int *)key;
}
return 0;
}
void free_gtp_signaling_field(void *data)
{
int i=0;
struct gtp_signaling_field *signal=(struct gtp_signaling_field *)data;
if(data==NULL)
{
return ;
}
for(i=0; i<GTP_FIELD_MAX; i++)
{
if(signal->ie_unit[i].value!=NULL)
{
free(signal->ie_unit[i].value);
signal->ie_unit[i].value=NULL;
}
}
free(data);
data=NULL;
return ;
}
void tsg_free_gtp_signaling_field(void *data)
{
if(data!=NULL)
{
free_gtp_signaling_field(data);
data=NULL;
}
}
static int get_umts_user_info_form_hash(struct umts_user_info **user_info, unsigned int teid, int thread_seq)
{
long cb_ret=0;
struct umts_user_info tmp_user_info={0};
MESA_htable_search_cb(g_gtp_signaling_hash_handle, (unsigned char *)&(teid), sizeof(unsigned int), copy_user_info, (void *)&tmp_user_info, &cb_ret);
if(cb_ret>0)
{
tmp_user_info.ref_cnt=1;
*user_info=(struct umts_user_info *)calloc(1, sizeof(struct umts_user_info));
memcpy(*user_info, &tmp_user_info, sizeof(struct umts_user_info));
return 1;
}
return 0;
}
static int get_umts_user_info_form_redis(struct umts_user_info **user_info, unsigned int teid, int thread_seq)
{
(*user_info) = tsg_get_umts_user_info_form_redis(g_tsg_maat_feather, (long long)teid);
if((*user_info)!=NULL)
{
return 1;
}
return 0;
}
int session_runtine_attribute_get_umts_user_info(const struct streaminfo *a_stream, struct umts_user_info **user_info)
{
int ret=0;
unsigned int uplink=0,downlink=0;
if(g_tsg_para.scan_signaling_switch==SIGNALING_ORIGIN_NO)
{
return 0;
}
if(*user_info!=NULL)
{
return 1;
}
ret=is_gtp_tunnel(a_stream);
if(ret==0)
{
return 0;
}
ret=get_gtp_teid(a_stream, &uplink, &downlink);
if(ret==0)
{
return 0;
}
switch(g_tsg_para.scan_signaling_switch)
{
case SIGNALING_ORIGIN_HASH:
ret=get_umts_user_info_form_hash(user_info, uplink, a_stream->threadnum);
if(ret==1)
{
return 1;
}
ret=get_umts_user_info_form_hash(user_info, downlink, a_stream->threadnum);
if(ret==1)
{
return 1;
}
break;
case SIGNALING_ORIGIN_REDIS:
ret=get_umts_user_info_form_redis(user_info, uplink, a_stream->threadnum);
if(ret==1)
{
return 1;
}
ret=get_umts_user_info_form_redis(user_info, downlink, a_stream->threadnum);
if(ret==1)
{
return 1;
}
break;
default:
break;
}
return 0;
}
int tsg_gtp_signaling_hash_init(const char* conffile, void *logger)
{
MESA_load_profile_int_def(conffile, "GTP_SIGNALING", "HASH_TIMEOUT", &g_tsg_para.hash_timeout, 300);
MESA_load_profile_int_def(conffile, "GTP_SIGNALING", "HASH_THREAD_SAFE", &g_tsg_para.hash_thread_safe, 128);
MESA_load_profile_int_def(conffile, "GTP_SIGNALING", "HASH_SLOT_SIZE", &g_tsg_para.hash_slot_size, 1024*1024*32);
MESA_htable_create_args_t args;
memset(&args, 0, sizeof(args));
args.thread_safe=g_tsg_para.hash_thread_safe;
args.recursive=1;
args.max_elem_num=0;
args.data_free=free_gtp_signaling_field;
args.eliminate_type=HASH_ELIMINATE_ALGO_LRU;
args.expire_time=g_tsg_para.hash_timeout;
args.hash_slot_size=g_tsg_para.hash_slot_size;
args.key2index=gtp_c_key2index;
g_gtp_signaling_hash_handle=MESA_htable_create(&args, sizeof(MESA_htable_create_args_t));
if(g_gtp_signaling_hash_handle==NULL)
{
MESA_handle_runtime_log(logger, RLOG_LV_FATAL, "GTP_SIGNALING", "MESA_htable_create failed");
return -1;
}
char signaling_origin[32]={0};
MESA_load_profile_string_def(conffile, "GTP_SIGNALING", "SIGNALING_ORIGIN", signaling_origin, sizeof(signaling_origin), "HASH");
int length=strlen(signaling_origin);
if(length==2 && (strncasecmp("NO", signaling_origin, 2)==0))
{
g_tsg_para.scan_signaling_switch=SIGNALING_ORIGIN_NO;
}
else if(length==4 && (strncasecmp("HASH", signaling_origin, 4)==0))
{
g_tsg_para.scan_signaling_switch=SIGNALING_ORIGIN_HASH;
}
else if(length==5 && (strncasecmp("REDIS", signaling_origin, 5)==0))
{
g_tsg_para.scan_signaling_switch=SIGNALING_ORIGIN_REDIS;
}
return 0;
}