diff --git a/src/modules/sipdump/sipdump_mod.c b/src/modules/sipdump/sipdump_mod.c index bf2c90c20f9..cbb3dfe8aa1 100644 --- a/src/modules/sipdump/sipdump_mod.c +++ b/src/modules/sipdump/sipdump_mod.c @@ -34,6 +34,7 @@ #include "../../core/pt.h" #include "../../core/timer_proc.h" #include "../../core/mod_fix.h" +#include "../../core/fmsg.h" #include "../../core/events.h" #include "../../core/kemi.h" @@ -46,6 +47,10 @@ int sipdump_rotate = 7200; static int sipdump_wait = 100; static str sipdump_folder = str_init("/tmp"); static str sipdump_fprefix = str_init("kamailio-sipdump-"); +static int sipdump_mode = SIPDUMP_MODE_WFILE; +static str sipdump_event_callback = STR_NULL; + +static int sipdump_event_route_idx = -1; static int mod_init(void); static int child_init(int); @@ -56,6 +61,10 @@ static int w_sipdump_send(sip_msg_t *msg, char *ptag, char *str2); int sipdump_msg_received(sr_event_param_t *evp); int sipdump_msg_sent(sr_event_param_t *evp); +int pv_parse_sipdump_name(pv_spec_t *sp, str *in); +int pv_get_sipdump(sip_msg_t *msg, pv_param_t *param, + pv_value_t *res); + /* clang-format off */ static cmd_export_t cmds[]={ {"sipdump_send", (cmd_function)w_sipdump_send, 1, fixup_spve_null, @@ -64,21 +73,32 @@ static cmd_export_t cmds[]={ }; static param_export_t params[]={ - {"enable", PARAM_INT, &sipdump_enable}, - {"wait", PARAM_INT, &sipdump_wait}, - {"rotate", PARAM_INT, &sipdump_rotate}, - {"folder", PARAM_STR, &sipdump_folder}, - {"fprefix", PARAM_STR, &sipdump_fprefix}, + {"enable", PARAM_INT, &sipdump_enable}, + {"wait", PARAM_INT, &sipdump_wait}, + {"rotate", PARAM_INT, &sipdump_rotate}, + {"folder", PARAM_STR, &sipdump_folder}, + {"fprefix", PARAM_STR, &sipdump_fprefix}, + {"mode", PARAM_INT, &sipdump_mode}, + {"event_callback", PARAM_STR, &sipdump_event_callback}, + {0, 0, 0} }; +static pv_export_t mod_pvs[] = { + + { {"sipdump", (sizeof("sipdump")-1)}, PVT_OTHER, pv_get_sipdump, 0, + pv_parse_sipdump_name, 0, 0, 0 }, + + { {0, 0}, 0, 0, 0, 0, 0, 0, 0 } +}; + struct module_exports exports = { "sipdump", /* module name */ DEFAULT_DLFLAGS, /* dlopen flags */ cmds, /* exported functions */ params, /* exported parameters */ 0, /* exported rpc functions */ - 0, /* exported pseudo-variables */ + mod_pvs, /* exported pseudo-variables */ 0, /* response handling function */ mod_init, /* module init function */ child_init, /* per child init function */ @@ -92,6 +112,11 @@ struct module_exports exports = { */ static int mod_init(void) { + if(!(sipdump_mode & (SIPDUMP_MODE_WFILE | SIPDUMP_MODE_EVROUTE))) { + LM_ERR("invalid mode parameter\n"); + return -1; + } + if(sipdump_rpc_init()<0) { LM_ERR("failed to register rpc commands\n"); return -1; @@ -107,7 +132,18 @@ static int mod_init(void) return -1; } - register_basic_timers(1); + if(sipdump_mode & SIPDUMP_MODE_EVROUTE) { + sipdump_event_route_idx = route_lookup(&event_rt, "sipdump:msg"); + if (sipdump_event_route_idx>=0 && event_rt.rlist[sipdump_event_route_idx]==0) { + sipdump_event_route_idx = -1; /* disable */ + } + faked_msg_init(); + } + + if(sipdump_mode & SIPDUMP_MODE_WFILE) { + register_basic_timers(1); + } + sr_event_register_cb(SREV_NET_DATA_IN, sipdump_msg_received); sr_event_register_cb(SREV_NET_DATA_OUT, sipdump_msg_sent); @@ -123,6 +159,10 @@ static int child_init(int rank) if(rank != PROC_MAIN) return 0; + if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) { + return 0; + } + if(fork_basic_utimer(PROC_TIMER, "SIPDUMP WRITE TIMER", 1 /*socks flag*/, sipdump_timer_exec, NULL, sipdump_wait /*usec*/) < 0) { @@ -207,6 +247,11 @@ int ki_sipdump_send(sip_msg_t *msg, str *stag) if(!sipdump_enabled()) return 1; + if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) { + LM_WARN("writing to file is disabled - ignoring\n"); + return 1; + } + memset(&sdi, 0, sizeof(sipdump_info_t)); sdi.buf.s = msg->buf; @@ -266,6 +311,45 @@ static int w_sipdump_send(sip_msg_t *msg, char *ptag, char *str2) return ki_sipdump_send(msg, &stag); } +/** + * + */ +static sipdump_info_t* sipdump_event_info = NULL; + +/** + * + */ +void sipdump_event_route(sipdump_info_t* sdi) +{ + int backup_rt; + run_act_ctx_t ctx; + run_act_ctx_t *bctx; + sr_kemi_eng_t *keng = NULL; + str evname = str_init("sipdump:msg"); + sip_msg_t *fmsg = NULL; + + backup_rt = get_route_type(); + set_route_type(EVENT_ROUTE); + init_run_actions_ctx(&ctx); + fmsg = faked_msg_next(); + sipdump_event_info = sdi; + + if(sipdump_event_route_idx>=0) { + run_top_route(event_rt.rlist[sipdump_event_route_idx], fmsg, 0); + } else { + keng = sr_kemi_eng_get(); + if (keng!=NULL) { + bctx = sr_kemi_act_ctx_get(); + sr_kemi_act_ctx_set(&ctx); + (void)sr_kemi_route(keng, fmsg, EVENT_ROUTE, + &sipdump_event_callback, &evname); + sr_kemi_act_ctx_set(bctx); + } + } + sipdump_event_info = NULL; + set_route_type(backup_rt); +} + /** * */ @@ -306,6 +390,15 @@ int sipdump_msg_received(sr_event_param_t *evp) sdi.proto.s = "none"; sdi.proto.len = 4; get_valid_proto_string(evp->rcv->proto, 0, 0, &sdi.proto); + + if(sipdump_mode & SIPDUMP_MODE_EVROUTE) { + sipdump_event_route(&sdi); + } + + if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) { + return 0; + } + if(sipdump_buffer_write(&sdi, &wdata)<0) { LM_ERR("failed to write to buffer\n"); return -1; @@ -354,6 +447,14 @@ int sipdump_msg_sent(sr_event_param_t *evp) sdi.proto.len = 4; get_valid_proto_string(evp->dst->proto, 0, 0, &sdi.proto); + if(sipdump_mode & SIPDUMP_MODE_EVROUTE) { + sipdump_event_route(&sdi); + } + + if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) { + return 0; + } + if(sipdump_buffer_write(&sdi, &wdata)<0) { LM_ERR("failed to write to buffer\n"); return -1; @@ -381,6 +482,97 @@ static sr_kemi_t sr_kemi_sipdump_exports[] = { }; /* clang-format on */ +/** + * + */ +int pv_parse_sipdump_name(pv_spec_t *sp, str *in) +{ + if(sp==NULL || in==NULL || in->len<=0) + return -1; + + switch(in->len) + { + case 2: + if(strncmp(in->s, "af", 2)==0) + sp->pvp.pvn.u.isname.name.n = 3; + else goto error; + break; + case 3: + if(strncmp(in->s, "buf", 3)==0) + sp->pvp.pvn.u.isname.name.n = 1; + else if(strncmp(in->s, "len", 3)==0) + sp->pvp.pvn.u.isname.name.n = 2; + else if(strncmp(in->s, "tag", 3)==0) + sp->pvp.pvn.u.isname.name.n = 0; + else goto error; + break; + case 5: + if(strncmp(in->s, "proto", 5)==0) + sp->pvp.pvn.u.isname.name.n = 4; + else goto error; + break; + case 6: + if(strncmp(in->s, "sproto", 6)==0) + sp->pvp.pvn.u.isname.name.n = 5; + else if(strncmp(in->s, "src_ip", 6)==0) + sp->pvp.pvn.u.isname.name.n = 6; + else if(strncmp(in->s, "dst_ip", 6)==0) + sp->pvp.pvn.u.isname.name.n = 7; + else goto error; + break; + case 8: + if(strncmp(in->s, "src_port", 8)==0) + sp->pvp.pvn.u.isname.name.n = 8; + if(strncmp(in->s, "dst_port", 8)==0) + sp->pvp.pvn.u.isname.name.n = 9; + else goto error; + break; + default: + goto error; + } + sp->pvp.pvn.type = PV_NAME_INTSTR; + sp->pvp.pvn.u.isname.type = 0; + + return 0; + +error: + LM_ERR("unknown PV snd name %.*s\n", in->len, in->s); + return -1; +} + +/** + * + */ +int pv_get_sipdump(sip_msg_t *msg, pv_param_t *param, + pv_value_t *res) +{ + if (sipdump_event_info==NULL) { + return pv_get_null(msg, param, res); + } + + switch(param->pvn.u.isname.name.n) { + case 1: /* buf */ + return pv_get_strval(msg, param, res, &sipdump_event_info->buf); + case 2: /* len */ + return pv_get_uintval(msg, param, res, sipdump_event_info->buf.len); + case 3: /* af */ + return pv_get_strval(msg, param, res, &sipdump_event_info->af); + case 4: /* proto */ + return pv_get_strval(msg, param, res, &sipdump_event_info->proto); + case 6: /* src_ip*/ + return pv_get_strval(msg, param, res, &sipdump_event_info->src_ip); + case 7: /* dst_ip*/ + return pv_get_strval(msg, param, res, &sipdump_event_info->dst_ip); + case 8: /* src_port */ + return pv_get_uintval(msg, param, res, sipdump_event_info->src_port); + case 9: /* dst_port */ + return pv_get_uintval(msg, param, res, sipdump_event_info->dst_port); + default: + /* 0 - tag */ + return pv_get_strval(msg, param, res, &sipdump_event_info->tag); + } +} + /** * */ diff --git a/src/modules/sipdump/sipdump_write.h b/src/modules/sipdump/sipdump_write.h index 611fd10fd92..44e902a01cf 100644 --- a/src/modules/sipdump/sipdump_write.h +++ b/src/modules/sipdump/sipdump_write.h @@ -26,6 +26,9 @@ #include "../../core/str.h" #include "../../core/locking.h" +#define SIPDUMP_MODE_WFILE (1<<0) +#define SIPDUMP_MODE_EVROUTE (1<<1) + typedef struct sipdump_data { str data; struct sipdump_data *next;