268 lines
6.0 KiB
C++
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;
|
|
}
|
|
|