Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: preparations for RFC5424 syslog support #8457

Closed
wants to merge 12 commits into from
21 changes: 16 additions & 5 deletions doc/user/basic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,17 @@ Basic Config Commands
is used to start the daemon then this command is turned on by default
and cannot be turned off and the [no] form of the command is dissallowed.

.. clicmd:: log-filter WORD [DAEMON]
.. clicmd:: log filtered-file [FILENAME [LEVEL]]

Configure a destination file for filtered logs with the
:clicmd:`log filter-text WORD` command.

.. clicmd:: log filter-text WORD

This command forces logs to be filtered on a specific string. A log message
will only be printed if it matches on one of the filters in the log-filter
table. Can be daemon independent.
table. The filter only applies to file logging targets configured with
:clicmd:`log filtered-file [FILENAME [LEVEL]]`.

.. note::

Expand All @@ -183,10 +189,15 @@ Basic Config Commands
Log filters prevent this but you should still expect a small performance
hit due to filtering each of all those logs.

.. clicmd:: log-filter clear [DAEMON]
.. note::

This setting is not saved to ``frr.conf`` and not shown in
:clicmd:`show running-config`. It is intended for ephemeral debugging
purposes only.

.. clicmd:: clear log filter-text

This command clears all current filters in the log-filter table. Can be
daemon independent.
This command clears all current filters in the log-filter table.

.. clicmd:: service password-encryption

Expand Down
81 changes: 44 additions & 37 deletions lib/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -900,13 +900,31 @@ enum node_type node_parent(enum node_type node)
/* Execute command by argument vline vector. */
static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
struct vty *vty,
const struct cmd_element **cmd)
const struct cmd_element **cmd,
unsigned int up_level)
{
struct list *argv_list;
enum matcher_rv status;
const struct cmd_element *matched_element = NULL;
unsigned int i;
int xpath_index = vty->xpath_index;
int node = vty->node;

struct graph *cmdgraph = cmd_node_graph(cmdvec, vty->node);
/* only happens for legacy split config file load; need to check for
* a match before calling node_exit handlers below
*/
for (i = 0; i < up_level; i++) {
if (node <= CONFIG_NODE)
return CMD_NO_LEVEL_UP;

node = node_parent(node);

if (xpath_index > 0
&& vty_check_node_for_xpath_decrement(node, vty->node))
xpath_index--;
}

struct graph *cmdgraph = cmd_node_graph(cmdvec, node);
status = command_match(cmdgraph, vline, &argv_list, &matched_element);

if (cmd)
Expand All @@ -926,12 +944,16 @@ static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
}
}

for (i = 0; i < up_level; i++)
cmd_exit(vty);

// build argv array from argv list
struct cmd_token **argv = XMALLOC(
MTYPE_TMP, argv_list->count * sizeof(struct cmd_token *));
struct listnode *ln;
struct cmd_token *token;
unsigned int i = 0;

i = 0;
for (ALL_LIST_ELEMENTS_RO(argv_list, ln, token))
argv[i++] = token;

Expand Down Expand Up @@ -1012,7 +1034,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
vector_lookup(vline, index));

ret = cmd_execute_command_real(shifted_vline, FILTER_RELAXED,
vty, cmd);
vty, cmd, 0);

vector_free(shifted_vline);
vty->node = onode;
Expand All @@ -1021,7 +1043,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
}

saved_ret = ret =
cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd);
cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd, 0);

if (vtysh)
return saved_ret;
Expand All @@ -1038,7 +1060,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
onode))
vty->xpath_index--;
ret = cmd_execute_command_real(vline, FILTER_RELAXED,
vty, cmd);
vty, cmd, 0);
if (ret == CMD_SUCCESS || ret == CMD_WARNING
|| ret == CMD_NOT_MY_INSTANCE
|| ret == CMD_WARNING_CONFIG_FAILED)
Expand Down Expand Up @@ -1069,7 +1091,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
int cmd_execute_command_strict(vector vline, struct vty *vty,
const struct cmd_element **cmd)
{
return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd);
return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd, 0);
}

/*
Expand Down Expand Up @@ -1220,6 +1242,7 @@ int command_config_read_one_line(struct vty *vty,
{
vector vline;
int ret;
unsigned up_level = 0;

vline = cmd_make_strvec(vty->buf);

Expand All @@ -1230,36 +1253,20 @@ int command_config_read_one_line(struct vty *vty,
/* Execute configuration command : this is strict match */
ret = cmd_execute_command_strict(vline, vty, cmd);

// Climb the tree and try the command again at each node
if (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING
&& ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
&& vty->node != CONFIG_NODE) {
int saved_node = vty->node;
int saved_xpath_index = vty->xpath_index;

while (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING
&& vty->node > CONFIG_NODE) {
vty->node = node_parent(vty->node);
if (vty->xpath_index > 0
&& vty_check_node_for_xpath_decrement(vty->node,
saved_node))
vty->xpath_index--;
ret = cmd_execute_command_strict(vline, vty, cmd);
}

// If climbing the tree did not work then ignore the command and
// stay at the same node
if (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING) {
vty->node = saved_node;
vty->xpath_index = saved_xpath_index;
}
}
/* The logic for trying parent nodes is in cmd_execute_command_real()
* since calling ->node_exit() correctly is a bit involved. This is
* also the only reason CMD_NO_LEVEL_UP exists.
*/
while (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING
&& ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
&& ret != CMD_NO_LEVEL_UP)
ret = cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd,
++up_level);

if (ret == CMD_NO_LEVEL_UP)
ret = CMD_ERR_NO_MATCH;

if (ret != CMD_SUCCESS &&
ret != CMD_WARNING &&
Expand Down
1 change: 1 addition & 0 deletions lib/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ struct cmd_node {
#define CMD_SUSPEND 12
#define CMD_WARNING_CONFIG_FAILED 13
#define CMD_NOT_MY_INSTANCE 14
#define CMD_NO_LEVEL_UP 15

/* Argc max counts. */
#define CMD_ARGC_MAX 256
Expand Down
4 changes: 4 additions & 0 deletions lib/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,11 @@ CPP_NOTICE("time to remove this CONFDATE block")
#define PRIx64 "Lx"

#else /* !_FRR_ATTRIBUTE_PRINTFRR */
#ifdef __NetBSD__
#define PRINTFRR(a, b) __attribute__((format(gnu_syslog, a, b)))
#else
#define PRINTFRR(a, b) __attribute__((format(printf, a, b)))
#endif

/* these should be typedefs, but might also be #define */
#ifdef uint64_t
Expand Down
10 changes: 7 additions & 3 deletions lib/log_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,14 @@ int zlog_filter_dump(char *buf, size_t max_size)
return len;
}

static int search_buf(const char *buf)
static int search_buf(const char *buf, size_t len)
{
char *found = NULL;

frr_with_mutex(&logfilterlock) {
for (int i = 0; i < zlog_filter_count; i++) {
found = strstr(buf, zlog_filters[i]);
found = memmem(buf, len, zlog_filters[i],
strlen(zlog_filters[i]));
if (found != NULL)
return 0;
}
Expand All @@ -131,10 +132,13 @@ static void zlog_filterfile_fd(struct zlog_target *zt, struct zlog_msg *msgs[],
{
struct zlog_msg *msgfilt[nmsgs];
size_t i, o = 0;
const char *text;
size_t text_len;

for (i = 0; i < nmsgs; i++) {
if (zlog_msg_prio(msgs[i]) >= LOG_DEBUG
&& search_buf(zlog_msg_text(msgs[i], NULL)) < 0)
&& (text = zlog_msg_text(msgs[i], &text_len))
&& search_buf(text, text_len) < 0)
continue;

msgfilt[o++] = msgs[i];
Expand Down
25 changes: 19 additions & 6 deletions lib/log_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define ZLOG_MAXLVL(a, b) MAX(a, b)

DEFINE_HOOK(zlog_rotate, (), ());
DEFINE_HOOK(zlog_cli_show, (struct vty * vty), (vty));

static const int log_default_lvl = LOG_DEBUG;

Expand All @@ -57,7 +58,7 @@ static struct zlog_cfg_filterfile zt_filterfile = {
},
};

static const char *zlog_progname;
const char *zlog_progname;
static const char *zlog_protoname;

static const struct facility_map {
Expand Down Expand Up @@ -94,7 +95,14 @@ static const char * const zlog_priority[] = {
"notifications", "informational", "debugging", NULL,
};

static const char *facility_name(int facility)
const char *zlog_priority_str(int priority)
{
if (priority > LOG_DEBUG)
return "???";
return zlog_priority[priority];
}

const char *facility_name(int facility)
{
const struct facility_map *fm;

Expand All @@ -104,7 +112,7 @@ static const char *facility_name(int facility)
return "";
}

static int facility_match(const char *str)
int facility_match(const char *str)
{
const struct facility_map *fm;

Expand Down Expand Up @@ -194,6 +202,8 @@ DEFUN_NOSH (show_logging,
vty_out(vty, "Record priority: %s\n",
(zt_file.record_priority ? "enabled" : "disabled"));
vty_out(vty, "Timestamp precision: %d\n", zt_file.ts_subsec);

hook_call(zlog_cli_show, vty);
return CMD_SUCCESS;
}

Expand Down Expand Up @@ -588,8 +598,9 @@ DEFUN (no_config_log_filterfile,

DEFPY (log_filter,
log_filter_cmd,
"[no] log-filter WORD$filter",
"[no] log filter-text WORD$filter",
NO_STR
"Logging control\n"
FILTER_LOG_STR
"String to filter by\n")
{
Expand All @@ -616,8 +627,9 @@ DEFPY (log_filter,
/* Clear all log filters */
DEFPY (log_filter_clear,
log_filter_clear_cmd,
"clear log-filter",
"clear log filter-text",
CLEAR_STR
"Logging control\n"
FILTER_LOG_STR)
{
zlog_filter_clear();
Expand All @@ -627,8 +639,9 @@ DEFPY (log_filter_clear,
/* Show log filter */
DEFPY (show_log_filter,
show_log_filter_cmd,
"show log-filter",
"show logging filter-text",
SHOW_STR
"Show current logging configuration\n"
FILTER_LOG_STR)
{
char log_filters[ZLOG_FILTERS_MAX * (ZLOG_FILTER_LENGTH_MAX + 3)] = "";
Expand Down
5 changes: 5 additions & 0 deletions lib/log_vty.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ extern void log_config_write(struct vty *vty);
extern int log_level_match(const char *s);
extern void log_show_syslog(struct vty *vty);

extern int facility_match(const char *str);
extern const char *facility_name(int facility);

DECLARE_HOOK(zlog_rotate, (), ());
extern void zlog_rotate(void);

DECLARE_HOOK(zlog_cli_show, (struct vty * vty), (vty));

#ifdef __cplusplus
}
#endif
Expand Down
Loading