aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/sgsn/sgsn.h1
-rw-r--r--src/gprs/sgsn_cdr.c64
-rw-r--r--src/gprs/sgsn_main.c6
-rw-r--r--src/gprs/sgsn_vty.c26
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);