diff options
-rw-r--r-- | include/osmocom/sgsn/sgsn.h | 1 | ||||
-rw-r--r-- | src/gprs/sgsn_cdr.c | 64 | ||||
-rw-r--r-- | src/gprs/sgsn_main.c | 6 | ||||
-rw-r--r-- | src/gprs/sgsn_vty.c | 26 |
4 files changed, 70 insertions, 27 deletions
diff --git a/include/osmocom/sgsn/sgsn.h b/include/osmocom/sgsn/sgsn.h index 464a64fe0..7e0b5d477 100644 --- a/include/osmocom/sgsn/sgsn.h +++ b/include/osmocom/sgsn/sgsn.h @@ -52,6 +52,7 @@ enum sgsn_rate_ctr_keys { struct sgsn_cdr { char *filename; + bool trap; int interval; }; diff --git a/src/gprs/sgsn_cdr.c b/src/gprs/sgsn_cdr.c index bc051ac81..55aa66492 100644 --- a/src/gprs/sgsn_cdr.c +++ b/src/gprs/sgsn_cdr.c @@ -18,6 +18,8 @@ * */ +#include <osmocom/ctrl/control_if.h> + #include <osmocom/sgsn/sgsn.h> #include <osmocom/sgsn/signal.h> #include <osmocom/sgsn/gprs_utils.h> @@ -38,6 +40,7 @@ /* TODO...avoid going through a global */ extern struct sgsn_instance *sgsn; +extern struct ctrl_handle *g_ctrlh; /** * The CDR module will generate an entry like: @@ -59,6 +62,11 @@ extern struct sgsn_instance *sgsn; * CAUSE_FOR_TERM, # CAUSE_FOR_TERM */ +static void send_cdr_trap(char *value) +{ + if (ctrl_cmd_send_trap(g_ctrlh, "cdr-v1", value) < 0) + LOGP(DGPRS, LOGL_ERROR, "Failed to create and send TRAP cdr-v1\n"); +} static void maybe_print_header(FILE *cdr_file) { @@ -97,21 +105,27 @@ static void cdr_log_mm(struct sgsn_instance *inst, const char *ev, FILE *cdr_file; char buf[1024]; - if (!inst->cfg.cdr.filename) + if (!inst->cfg.cdr.filename && !inst->cfg.cdr.trap) return; - cdr_file = fopen(inst->cfg.cdr.filename, "a"); - if (!cdr_file) { - LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n", - inst->cfg.cdr.filename); - return; - } - - maybe_print_header(cdr_file); cdr_snprintf_mm(buf, sizeof(buf), ev, mmctx); - fprintf(cdr_file, "%s\n", buf); - fclose(cdr_file); + if (inst->cfg.cdr.trap) + send_cdr_trap(buf); + + if (inst->cfg.cdr.filename) { + cdr_file = fopen(inst->cfg.cdr.filename, "a"); + if (!cdr_file) { + LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n", + inst->cfg.cdr.filename); + return; + } + + maybe_print_header(cdr_file); + fprintf(cdr_file, "%s\n", buf); + + fclose(cdr_file); + } } static void extract_eua(struct ul66_t *eua, char *eua_addr) @@ -200,20 +214,26 @@ static void cdr_log_pdp(struct sgsn_instance *inst, const char *ev, FILE *cdr_file; char buf[1024]; - if (!inst->cfg.cdr.filename) - return; - - cdr_file = fopen(inst->cfg.cdr.filename, "a"); - if (!cdr_file) { - LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n", - inst->cfg.cdr.filename); + if (!inst->cfg.cdr.filename && !inst->cfg.cdr.trap) return; - } - maybe_print_header(cdr_file); cdr_snprintf_pdp(buf, sizeof(buf), ev, pdp); - fprintf(cdr_file, "%s\n", buf); - fclose(cdr_file); + + if (inst->cfg.cdr.trap) + send_cdr_trap(buf); + + if (inst->cfg.cdr.filename) { + cdr_file = fopen(inst->cfg.cdr.filename, "a"); + if (!cdr_file) { + LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n", + inst->cfg.cdr.filename); + return; + } + + maybe_print_header(cdr_file); + fprintf(cdr_file, "%s\n", buf); + fclose(cdr_file); + } } static void cdr_pdp_timeout(void *_data) diff --git a/src/gprs/sgsn_main.c b/src/gprs/sgsn_main.c index fe4192bbd..b2a028c43 100644 --- a/src/gprs/sgsn_main.c +++ b/src/gprs/sgsn_main.c @@ -76,6 +76,7 @@ #include <getopt.h> void *tall_bsc_ctx; +struct ctrl_handle *g_ctrlh; struct gprs_ns_inst *sgsn_nsi; static int daemonize = 0; @@ -367,7 +368,6 @@ static bool file_exists(const char *path) int main(int argc, char **argv) { - struct ctrl_handle *ctrl; int rc; #if BUILD_IU struct osmo_sccp_instance *sccp; @@ -454,9 +454,9 @@ int main(int argc, char **argv) /* start control interface after reading config for * ctrl_vty_get_bind_addr() */ - ctrl = sgsn_controlif_setup(NULL, ctrl_vty_get_bind_addr(), + g_ctrlh = sgsn_controlif_setup(NULL, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_SGSN); - if (!ctrl) { + if (!g_ctrlh) { LOGP(DGPRS, LOGL_ERROR, "Failed to create CTRL interface.\n"); exit(1); } diff --git a/src/gprs/sgsn_vty.c b/src/gprs/sgsn_vty.c index a01de2d7a..c8dfc437e 100644 --- a/src/gprs/sgsn_vty.c +++ b/src/gprs/sgsn_vty.c @@ -233,6 +233,10 @@ static int config_write_sgsn(struct vty *vty) vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE); else vty_out(vty, " no cdr filename%s", VTY_NEWLINE); + if (g_cfg->cdr.trap) + vty_out(vty, " cdr trap%s", VTY_NEWLINE); + else + vty_out(vty, " no cdr trap%s", VTY_NEWLINE); vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE); vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE); @@ -1100,7 +1104,7 @@ DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd, DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd, "cdr filename NAME", - "CDR\nSet filename\nname\n") + "CDR\nEnable saving CDR to filename\nname\n") { talloc_free(g_cfg->cdr.filename); g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]); @@ -1109,13 +1113,29 @@ DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd, DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd, "no cdr filename", - NO_STR "CDR\nDisable CDR generation\n") + NO_STR "CDR\nDisable saving CDR to file\n") { talloc_free(g_cfg->cdr.filename); g_cfg->cdr.filename = NULL; return CMD_SUCCESS; } +DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd, + "cdr trap", + "CDR\nEnable sending CDR via TRAP CTRL messages\n") +{ + g_cfg->cdr.trap = true; + return CMD_SUCCESS; +} + +DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd, + "no cdr trap", + NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n") +{ + g_cfg->cdr.trap = false; + return CMD_SUCCESS; +} + DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd, "cdr interval <1-2147483647>", "CDR\nPDP periodic log interval\nSeconds\n") @@ -1250,6 +1270,8 @@ int sgsn_vty_init(struct sgsn_config *cfg) install_element(SGSN_NODE, &cfg_no_apn_name_cmd); install_element(SGSN_NODE, &cfg_cdr_filename_cmd); install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd); + install_element(SGSN_NODE, &cfg_cdr_trap_cmd); + install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd); install_element(SGSN_NODE, &cfg_cdr_interval_cmd); install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd); install_element(SGSN_NODE, &cfg_grx_ggsn_cmd); |