#include #include #include #include "recorder.h" #define LINE_STR "Configure Recording for given Line\nE1/T1 Line Number\n" DEFUN(cfg_recorder, cfg_recorder_cmd, "recorder", "Configuration of E1 Recorder\n") { vty->node = RECORDER_NODE; return CMD_SUCCESS; } static const struct e1inp_line_ops dummy_e1i_line_ops = { .sign_link_up = NULL, .sign_link_down = NULL, .sign_link = NULL, }; DEFUN(cfg_rec_line_ts_mode, cfg_rec_line_ts_mode_cmd, "line <0-255> ts <1-31> mode (none|hdlc|trau|raw)", LINE_STR "E1/T1 Timeslot Number\n" "E1/T1 Timeslot Number\n" "Recording Mode\n" "No recording\n" "Signalling Data (HDLC)\n" "TRAU Frames\n" "Raw Data\n") { int line_nr = atoi(argv[0]); int ts_nr = atoi(argv[1]); int mode = get_string_value(e1inp_ts_type_names, argv[2]); struct e1inp_line *line; struct e1inp_ts *ts; if (mode < 0) { vty_out(vty, "Cannot parse mode %s%s", argv[2], VTY_NEWLINE); return CMD_WARNING; } line = e1inp_line_find(line_nr); if (!line) { vty_out(vty, "Cannot find line %d%s", line_nr, VTY_NEWLINE); return CMD_WARNING; } if (ts_nr >= line->num_ts) { vty_out(vty, "Timeslot %d is too large%s", ts_nr, VTY_NEWLINE); return CMD_WARNING; } ts = &line->ts[ts_nr-1]; e1inp_line_bind_ops(line, &dummy_e1i_line_ops); vty_out(vty, "Line %u TS %u mode %u%s", line_nr, ts_nr, mode, VTY_NEWLINE); switch (mode) { case E1INP_TS_TYPE_NONE: /* TOOD: have eqinp_ts_config_none ? */ ts->type = E1INP_TS_TYPE_NONE; break; case E1INP_TS_TYPE_HDLC: e1inp_ts_config_hdlc(ts, line, &e1ts_raw_recv); break; case E1INP_TS_TYPE_RAW: e1inp_ts_config_raw(ts, line, &e1ts_raw_recv); break; default: vty_out(vty, "Unknown mode %u ?!?%s", mode, VTY_NEWLINE); break; } /* notify driver of change */ e1inp_line_update(line); return CMD_SUCCESS; } DEFUN(cfg_rec_line_mirror, cfg_rec_line_mirror_cmd, "line <0-255> mirror <0-255>", LINE_STR "Mirror this line to another line\n" "E1/T1 Line Number\n") { uint8_t line_nr = atoi(argv[0]); uint8_t peer_nr = atoi(argv[1]); struct e1_recorder_line *line = &g_recorder.line[line_nr]; struct e1_recorder_line *peer = &g_recorder.line[peer_nr]; /* look up morror peer and enable mirror flag on peer */ if (peer->mirror.enabled && peer->mirror.line_nr != line_nr) { vty_out(vty, "Peer line %u already part of another mirror%s", peer_nr, VTY_NEWLINE); return CMD_WARNING; } peer->mirror.enabled = true; peer->mirror.line_nr = line_nr; /* enable mirror flag of current line */ if (line->mirror.enabled && line->mirror.line_nr != peer_nr) { vty_out(vty, "Line %u already part of another mirror%s", line_nr, VTY_NEWLINE); return CMD_WARNING; } line->mirror.enabled = true; line->mirror.line_nr = peer_nr; return CMD_SUCCESS; } DEFUN(cfg_rec_no_line_mirror, cfg_rec_no_line_mirror_cmd, "no line <0-255> mirror", LINE_STR "Mirror this line to another line\n" "E1/T1 Line Number\n") { uint8_t line_nr = atoi(argv[0]); struct e1_recorder_line *line = &g_recorder.line[line_nr]; struct e1_recorder_line *peer; if (!line->mirror.enabled) return CMD_WARNING; /* look up morror peer (if any) and disable mirror flag on peer */ peer = &g_recorder.line[line->mirror.line_nr]; if (peer->mirror.enabled) { peer->mirror.enabled = false; peer->mirror.line_nr = 0; } /* dsiable mirror flag of current line */ if (line->mirror.enabled){ line->mirror.enabled = false; line->mirror.line_nr = 0; } return CMD_SUCCESS; } DEFUN(cfg_rec_save_path, cfg_rec_save_path_cmd, "storage-path PATH", "Configure the directory for storing recordings\n" "Directory to which recordings are stored\n") { osmo_talloc_replace_string(NULL, &g_recorder.storage_path, argv[0]); return CMD_SUCCESS; } DEFUN(cfg_rec_file_size, cfg_rec_file_size_cmd, "file-size-mb <1-9999999>", "Configure the maximum file size before starting new file\n" "Megabytes\n") { g_recorder.max_file_size_mb = atoi(argv[0]); return CMD_SUCCESS; } static void config_write_recorder_line(struct vty *vty, unsigned int lnr) { struct e1inp_line *line = e1inp_line_find(lnr); struct e1_recorder_line *rline = &g_recorder.line[lnr]; unsigned int i; if (rline->mirror.enabled) { vty_out(vty, " line %u mirror %u%s", lnr, rline->mirror.line_nr, VTY_NEWLINE); } if (!line) return; for (i = 0; i < line->num_ts; i++) { struct e1inp_ts *ts = &line->ts[i]; const char *mode_str; mode_str = get_value_string(e1inp_ts_type_names, ts->type); vty_out(vty, " line %u ts %u mode %s%s", lnr, ts->num, mode_str, VTY_NEWLINE); } } static int config_write_recorder(struct vty *vty) { unsigned int i; vty_out(vty, "recorder%s", VTY_NEWLINE); vty_out(vty, " file-size-mb %u%s", g_recorder.max_file_size_mb, VTY_NEWLINE); vty_out(vty, " storage-path %s%s", g_recorder.storage_path, VTY_NEWLINE); for (i = 0; i < 255; i++) { config_write_recorder_line(vty, i); } return 0; } static struct cmd_node cfg_recorder_node = { RECORDER_NODE, "%s(config-recorder)# ", 1, }; void recorder_vty_init(void) { install_element(CONFIG_NODE, &cfg_recorder_cmd); install_node(&cfg_recorder_node, config_write_recorder); install_element(RECORDER_NODE, &cfg_rec_line_ts_mode_cmd); install_element(RECORDER_NODE, &cfg_rec_line_mirror_cmd); install_element(RECORDER_NODE, &cfg_rec_no_line_mirror_cmd); install_element(RECORDER_NODE, &cfg_rec_save_path_cmd); install_element(RECORDER_NODE, &cfg_rec_file_size_cmd); }