2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Virtual terminal [aka TeletYpe] interface routine
|
2017-05-13 10:25:29 +02:00
|
|
|
* Copyright (C) 1997 Kunihiro Ishiguro
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#ifndef _ZEBRA_VTY_H
|
|
|
|
#define _ZEBRA_VTY_H
|
|
|
|
|
2018-05-13 02:14:22 +02:00
|
|
|
#include <sys/types.h>
|
2022-10-31 21:23:51 +01:00
|
|
|
#ifdef HAVE_LIBPCRE2_POSIX
|
|
|
|
#ifndef _FRR_PCRE2_POSIX
|
|
|
|
#define _FRR_PCRE2_POSIX
|
|
|
|
#include <pcre2posix.h>
|
|
|
|
#endif /* _FRR_PCRE2_POSIX */
|
|
|
|
#elif defined(HAVE_LIBPCREPOSIX)
|
2020-02-16 20:14:04 +01:00
|
|
|
#include <pcreposix.h>
|
|
|
|
#else
|
2018-05-13 02:14:22 +02:00
|
|
|
#include <regex.h>
|
2022-10-31 21:23:51 +01:00
|
|
|
#endif /* HAVE_LIBPCRE2_POSIX */
|
2018-05-13 02:14:22 +02:00
|
|
|
|
2023-03-07 20:22:48 +01:00
|
|
|
#include "frrevent.h"
|
2007-04-29 00:14:10 +02:00
|
|
|
#include "log.h"
|
2012-04-10 16:57:23 +02:00
|
|
|
#include "sockunion.h"
|
2016-09-26 18:36:49 +02:00
|
|
|
#include "qobj.h"
|
2017-08-23 20:22:31 +02:00
|
|
|
#include "compiler.h"
|
2017-12-07 20:31:48 +01:00
|
|
|
#include "northbound.h"
|
2019-12-04 08:10:42 +01:00
|
|
|
#include "zlog_live.h"
|
2023-03-14 11:36:06 +01:00
|
|
|
#include "libfrr.h"
|
2023-03-08 23:26:38 +01:00
|
|
|
#include "mgmt_fe_client.h"
|
2003-06-15 03:28:29 +02:00
|
|
|
|
2019-02-07 23:10:31 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2021-11-17 11:39:00 +01:00
|
|
|
struct json_object;
|
|
|
|
|
2017-01-11 00:33:50 +01:00
|
|
|
#define VTY_BUFSIZ 4096
|
2002-12-13 21:15:29 +01:00
|
|
|
#define VTY_MAXHIST 20
|
2017-12-07 20:31:48 +01:00
|
|
|
#define VTY_MAXDEPTH 8
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-05-14 21:49:33 +02:00
|
|
|
#define VTY_MAXCFGCHANGES 16
|
lib, ripd: rework API for converted CLI commands
When editing the candidate configuration, the northbound must ensure
that either all changes made by a command are accepted or none are.
This is done to prevent inconsistent states where only parts of a
command are applied in the event any error happens.
The previous API for converted commands, the nb_cli_cfg_change()
function, required callers to pass an array containing all changes
that needed to be applied in the candidate configuration. The
problem with this API is that it was very inconvenient for complex
commands, which change different configuration options depending
on several factors. This required users to manipulate the array
of configuration changes using low-level primitives, making it
complicated to implement some commands.
To solve this problem, introduce a new API based on the two following
functions:
- nb_cli_enqueue_change()
- nb_cli_apply_changes()
The first function is used to enqueue configuration changes, one
at time. Then the nb_cli_apply_changes() function is used to apply
all the enqueued configuration changes.
To implement this, a static-sized array was allocated in the "vty"
structure, along with a counter of enqueued changes. This eliminates
the need to declare an array of configuration changes in every
converted CLI command, simplifying things quite considerably.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-11-26 18:30:14 +01:00
|
|
|
|
2018-10-11 15:43:32 +02:00
|
|
|
struct vty_error {
|
|
|
|
char error_buf[VTY_BUFSIZ];
|
|
|
|
uint32_t line_num;
|
2023-05-09 15:19:24 +02:00
|
|
|
int cmd_ret;
|
2018-10-11 15:43:32 +02:00
|
|
|
};
|
|
|
|
|
lib, ripd: rework API for converted CLI commands
When editing the candidate configuration, the northbound must ensure
that either all changes made by a command are accepted or none are.
This is done to prevent inconsistent states where only parts of a
command are applied in the event any error happens.
The previous API for converted commands, the nb_cli_cfg_change()
function, required callers to pass an array containing all changes
that needed to be applied in the candidate configuration. The
problem with this API is that it was very inconvenient for complex
commands, which change different configuration options depending
on several factors. This required users to manipulate the array
of configuration changes using low-level primitives, making it
complicated to implement some commands.
To solve this problem, introduce a new API based on the two following
functions:
- nb_cli_enqueue_change()
- nb_cli_apply_changes()
The first function is used to enqueue configuration changes, one
at time. Then the nb_cli_apply_changes() function is used to apply
all the enqueued configuration changes.
To implement this, a static-sized array was allocated in the "vty"
structure, along with a counter of enqueued changes. This eliminates
the need to declare an array of configuration changes in every
converted CLI command, simplifying things quite considerably.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-11-26 18:30:14 +01:00
|
|
|
struct vty_cfg_change {
|
2018-12-04 15:34:09 +01:00
|
|
|
char xpath[XPATH_MAXLEN];
|
lib, ripd: rework API for converted CLI commands
When editing the candidate configuration, the northbound must ensure
that either all changes made by a command are accepted or none are.
This is done to prevent inconsistent states where only parts of a
command are applied in the event any error happens.
The previous API for converted commands, the nb_cli_cfg_change()
function, required callers to pass an array containing all changes
that needed to be applied in the candidate configuration. The
problem with this API is that it was very inconvenient for complex
commands, which change different configuration options depending
on several factors. This required users to manipulate the array
of configuration changes using low-level primitives, making it
complicated to implement some commands.
To solve this problem, introduce a new API based on the two following
functions:
- nb_cli_enqueue_change()
- nb_cli_apply_changes()
The first function is used to enqueue configuration changes, one
at time. Then the nb_cli_apply_changes() function is used to apply
all the enqueued configuration changes.
To implement this, a static-sized array was allocated in the "vty"
structure, along with a counter of enqueued changes. This eliminates
the need to declare an array of configuration changes in every
converted CLI command, simplifying things quite considerably.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-11-26 18:30:14 +01:00
|
|
|
enum nb_operation operation;
|
|
|
|
const char *value;
|
|
|
|
};
|
|
|
|
|
2021-10-22 14:15:55 +02:00
|
|
|
PREDECL_DLIST(vtys);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* VTY struct. */
|
|
|
|
struct vty {
|
2021-10-22 14:15:55 +02:00
|
|
|
struct vtys_item itm;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* File descripter of this vty. */
|
|
|
|
int fd;
|
|
|
|
|
2013-05-30 16:31:49 +02:00
|
|
|
/* output FD, to support stdin/stdout combination */
|
|
|
|
int wfd;
|
|
|
|
|
2018-05-15 00:13:03 +02:00
|
|
|
/* File output, used for VTYSH only */
|
|
|
|
FILE *of;
|
|
|
|
FILE *of_saved;
|
|
|
|
|
|
|
|
/* whether we are using pager or not */
|
|
|
|
bool is_paged;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Is this vty connect to file or not */
|
2023-05-09 15:19:24 +02:00
|
|
|
enum { VTY_TERM, /* telnet conn or stdin/stdout UI */
|
|
|
|
VTY_FILE, /* reading and writing config files */
|
|
|
|
VTY_SHELL, /* vtysh client side UI */
|
|
|
|
VTY_SHELL_SERV, /* server-side vtysh connection */
|
|
|
|
} type;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* Node status of this vty */
|
|
|
|
int node;
|
|
|
|
|
|
|
|
/* Failure count */
|
|
|
|
int fail;
|
|
|
|
|
2018-05-13 02:14:22 +02:00
|
|
|
/* Output filer regex */
|
|
|
|
bool filter;
|
|
|
|
regex_t include;
|
|
|
|
|
2018-06-06 21:09:44 +02:00
|
|
|
/* Line buffer */
|
|
|
|
struct buffer *lbuf;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Output buffer. */
|
|
|
|
struct buffer *obuf;
|
|
|
|
|
|
|
|
/* Command input buffer */
|
|
|
|
char *buf;
|
|
|
|
|
2015-07-28 05:30:22 +02:00
|
|
|
/* Command input error buffer */
|
2018-10-11 15:43:32 +02:00
|
|
|
struct list *error;
|
2015-07-28 05:30:22 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Command cursor point */
|
|
|
|
int cp;
|
|
|
|
|
|
|
|
/* Command length */
|
|
|
|
int length;
|
|
|
|
|
|
|
|
/* Command max length. */
|
|
|
|
int max;
|
|
|
|
|
|
|
|
/* Histry of command */
|
|
|
|
char *hist[VTY_MAXHIST];
|
|
|
|
|
|
|
|
/* History lookup current point */
|
|
|
|
int hp;
|
|
|
|
|
|
|
|
/* History insert end point */
|
|
|
|
int hindex;
|
|
|
|
|
lib, ripd: rework API for converted CLI commands
When editing the candidate configuration, the northbound must ensure
that either all changes made by a command are accepted or none are.
This is done to prevent inconsistent states where only parts of a
command are applied in the event any error happens.
The previous API for converted commands, the nb_cli_cfg_change()
function, required callers to pass an array containing all changes
that needed to be applied in the candidate configuration. The
problem with this API is that it was very inconvenient for complex
commands, which change different configuration options depending
on several factors. This required users to manipulate the array
of configuration changes using low-level primitives, making it
complicated to implement some commands.
To solve this problem, introduce a new API based on the two following
functions:
- nb_cli_enqueue_change()
- nb_cli_apply_changes()
The first function is used to enqueue configuration changes, one
at time. Then the nb_cli_apply_changes() function is used to apply
all the enqueued configuration changes.
To implement this, a static-sized array was allocated in the "vty"
structure, along with a counter of enqueued changes. This eliminates
the need to declare an array of configuration changes in every
converted CLI command, simplifying things quite considerably.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-11-26 18:30:14 +01:00
|
|
|
/* Changes enqueued to be applied in the candidate configuration. */
|
|
|
|
size_t num_cfg_changes;
|
2023-03-08 23:26:38 +01:00
|
|
|
struct nb_cfg_change cfg_changes[VTY_MAXCFGCHANGES];
|
lib, ripd: rework API for converted CLI commands
When editing the candidate configuration, the northbound must ensure
that either all changes made by a command are accepted or none are.
This is done to prevent inconsistent states where only parts of a
command are applied in the event any error happens.
The previous API for converted commands, the nb_cli_cfg_change()
function, required callers to pass an array containing all changes
that needed to be applied in the candidate configuration. The
problem with this API is that it was very inconvenient for complex
commands, which change different configuration options depending
on several factors. This required users to manipulate the array
of configuration changes using low-level primitives, making it
complicated to implement some commands.
To solve this problem, introduce a new API based on the two following
functions:
- nb_cli_enqueue_change()
- nb_cli_apply_changes()
The first function is used to enqueue configuration changes, one
at time. Then the nb_cli_apply_changes() function is used to apply
all the enqueued configuration changes.
To implement this, a static-sized array was allocated in the "vty"
structure, along with a counter of enqueued changes. This eliminates
the need to declare an array of configuration changes in every
converted CLI command, simplifying things quite considerably.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-11-26 18:30:14 +01:00
|
|
|
|
2017-12-07 20:31:48 +01:00
|
|
|
/* XPath of the current node */
|
|
|
|
int xpath_index;
|
|
|
|
char xpath[VTY_MAXDEPTH][XPATH_MAXLEN];
|
|
|
|
|
2023-03-14 11:36:06 +01:00
|
|
|
/*
|
|
|
|
* Keep track of how many SET_CFG requests has been sent so far that
|
|
|
|
* has not been committed yet.
|
|
|
|
*/
|
|
|
|
size_t mgmt_num_pending_setcfg;
|
|
|
|
|
2018-11-26 19:47:22 +01:00
|
|
|
/* In configure mode. */
|
|
|
|
bool config;
|
|
|
|
|
2017-12-07 20:31:48 +01:00
|
|
|
/* Private candidate configuration mode. */
|
|
|
|
bool private_config;
|
|
|
|
|
|
|
|
/* Candidate configuration. */
|
|
|
|
struct nb_config *candidate_config;
|
|
|
|
|
|
|
|
/* Base candidate configuration. */
|
|
|
|
struct nb_config *candidate_config_base;
|
|
|
|
|
lib: introduce configuration back-off timer for YANG-modeled commands
When using the default CLI mode, the northbound layer needs to create
a separate transaction to process each YANG-modeled command since
they are supposed to be applied immediately (there's no candidate
configuration nor the "commit" command like in the transactional
CLI). The problem is that configuration transactions have an overhead
associated to them, in big part because of the use of some heavy
libyang functions like `lyd_validate()` and `lyd_diff()`. As of
now this overhead is substantial and doesn't scale well when large
numbers of transactions need to be performed in sequence.
As an example, loading 50k prefix-lists using a single transaction
takes about 2 seconds on a modern CPU. Loading the same 50k
prefix-lists using 50k transactions can take more than an hour
to complete (which is unacceptable by any standard). To fix this
problem, some heavy optimization work needs to be done on libyang and
on the FRR northbound itself too (e.g. perform partial configuration
diffs whenever possible). This, however, should be a long term
effort since these optimizations shouldn't be trivial to implement
and we're far from having the performance numbers we need.
In the meanwhile, this commit introduces a simple but efficient
workaround to alleviate the issue. In short, a new back-off timer
was introduced in the CLI to monitor and detect when too many
YANG-modeled commands are being received at the same time. When
a certain threshold is reached (100 YANG-modeled commands within
one second), the northbound starts to group all subsequent commands
into a single large transaction, which allows them to be processed
much faster (e.g. seconds and not hours). It's essentially a
protection mechanism that creates dynamically-sized transactions
when necessary to prevent performance issues from happening. This
mechanism is enabled both when parsing configuration files and when
reading commands from a terminal.
The downside of this optimization is that, if several YANG-modeled
commands are grouped into the same transaction and at least one of
them fails, the whole transaction is rejected. This is undesirable
since users don't expect transactional behavior when that's not
enabled explicitly. To minimize this issue, the CLI will log all
commands that were rejected whenever that happens, to make the
user aware of what happened and have enough information to fix
the problem. Commands that fail due to parsing errors or CLI-level
validations in general are rejected separately.
Again, this proposed workaround is intended to be temporary. The
goal is to provided a quick fix to issues like #6658 while we work
on better long-term solutions.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2020-07-02 19:43:36 +02:00
|
|
|
/* Dynamic transaction information. */
|
2021-05-28 21:16:18 +02:00
|
|
|
bool pending_allowed;
|
|
|
|
bool pending_commit;
|
2023-03-08 23:26:38 +01:00
|
|
|
bool no_implicit_commit;
|
lib: introduce configuration back-off timer for YANG-modeled commands
When using the default CLI mode, the northbound layer needs to create
a separate transaction to process each YANG-modeled command since
they are supposed to be applied immediately (there's no candidate
configuration nor the "commit" command like in the transactional
CLI). The problem is that configuration transactions have an overhead
associated to them, in big part because of the use of some heavy
libyang functions like `lyd_validate()` and `lyd_diff()`. As of
now this overhead is substantial and doesn't scale well when large
numbers of transactions need to be performed in sequence.
As an example, loading 50k prefix-lists using a single transaction
takes about 2 seconds on a modern CPU. Loading the same 50k
prefix-lists using 50k transactions can take more than an hour
to complete (which is unacceptable by any standard). To fix this
problem, some heavy optimization work needs to be done on libyang and
on the FRR northbound itself too (e.g. perform partial configuration
diffs whenever possible). This, however, should be a long term
effort since these optimizations shouldn't be trivial to implement
and we're far from having the performance numbers we need.
In the meanwhile, this commit introduces a simple but efficient
workaround to alleviate the issue. In short, a new back-off timer
was introduced in the CLI to monitor and detect when too many
YANG-modeled commands are being received at the same time. When
a certain threshold is reached (100 YANG-modeled commands within
one second), the northbound starts to group all subsequent commands
into a single large transaction, which allows them to be processed
much faster (e.g. seconds and not hours). It's essentially a
protection mechanism that creates dynamically-sized transactions
when necessary to prevent performance issues from happening. This
mechanism is enabled both when parsing configuration files and when
reading commands from a terminal.
The downside of this optimization is that, if several YANG-modeled
commands are grouped into the same transaction and at least one of
them fails, the whole transaction is rejected. This is undesirable
since users don't expect transactional behavior when that's not
enabled explicitly. To minimize this issue, the CLI will log all
commands that were rejected whenever that happens, to make the
user aware of what happened and have enough information to fix
the problem. Commands that fail due to parsing errors or CLI-level
validations in general are rejected separately.
Again, this proposed workaround is intended to be temporary. The
goal is to provided a quick fix to issues like #6658 while we work
on better long-term solutions.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2020-07-02 19:43:36 +02:00
|
|
|
char *pending_cmds_buf;
|
|
|
|
size_t pending_cmds_buflen;
|
|
|
|
size_t pending_cmds_bufpos;
|
|
|
|
|
2018-12-06 23:37:05 +01:00
|
|
|
/* Confirmed-commit timeout and rollback configuration. */
|
2022-03-01 22:18:12 +01:00
|
|
|
struct event *t_confirmed_commit_timeout;
|
2018-12-06 23:37:05 +01:00
|
|
|
struct nb_config *confirmed_commit_rollback;
|
|
|
|
|
2016-09-26 18:36:49 +02:00
|
|
|
/* qobj object ID (replacement for "index") */
|
|
|
|
uint64_t qobj_index;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2016-09-27 16:51:58 +02:00
|
|
|
/* qobj second-level object ID (replacement for "index_sub") */
|
|
|
|
uint64_t qobj_index_sub;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* For escape character. */
|
|
|
|
unsigned char escape;
|
|
|
|
|
|
|
|
/* Current vty status. */
|
2019-12-04 00:17:50 +01:00
|
|
|
enum {
|
|
|
|
VTY_NORMAL,
|
|
|
|
VTY_CLOSE,
|
|
|
|
VTY_MORE,
|
|
|
|
VTY_MORELINE,
|
|
|
|
VTY_PASSFD,
|
|
|
|
} status;
|
|
|
|
|
|
|
|
/* vtysh socket/fd passing (for terminal monitor) */
|
|
|
|
int pass_fd;
|
|
|
|
|
|
|
|
/* CLI command return value (likely CMD_SUCCESS) when pass_fd != -1 */
|
|
|
|
uint8_t pass_fd_status[4];
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2019-12-04 08:10:42 +01:00
|
|
|
/* live logging target / terminal monitor */
|
|
|
|
struct zlog_live_cfg live_log;
|
|
|
|
|
2005-02-23 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* buffer.h: Make the struct buffer and struct buffer_data structures
private by moving them inside buffer.c. Add comments for all
functions. Rename buffer_write as buffer_put (to be more consistent
with the buffer_putc and buffer_putstr functions). Declare a new
buffer_write function that is used to write data to a file descriptor
and/or add it to the buffer queue. Remove unused function
buffer_flush_vty_all. Create a new enum typedef buffer_status_t
to be used as the return code for all buffer_flush* functions
and buffer_write.
* buffer.c: The struct buffer and struct buffer_data declarations
are now private to this file. In conjunction with that, remove
some unnecessary fields: struct buffer (alloc, unused_head,
unused_tail, length), struct buffer_data (prev).
(buffer_data_new) Removed: functionality incorporated into buffer_add.
(buffer_data_free) Removed: use a macro BUFFER_DATA_FREE instead.
(buffer_new) Use calloc instead of malloc + memset(zero).
Supply an appropriate default size if the specified size is 0.
(buffer_free) Eliminate code duplication by calling buffer_reset to
free the contents of the buffer (and remove unused code related
to unused_head).
(buffer_empty,buffer_putc,buffer_putstr) Aesthetic change (make more
compact).
(buffer_reset) Use macro BUFFER_DATA_FREE. No need to set
alloc and length to 0 (these fields have been removed).
(buffer_add) Fix scope to be static. Call XMALLOC directly instead
of calling removed buffer_data_new function. Simplify the logic
(since it's now a singly-linked list instead of doubly-linked).
(buffer_write) Renamed to buffer_put. Change to void, since return
code of 1 was meaningless. No need to adjust length field, since
it has been removed.
(buffer_putw,buffer_flush,buffer_flush_vty_all,buffer_flush_vty)
Remove unused functions.
(buffer_flush_all) Rewrite using buffer_flush_available to eliminate
a possible failure mode if IOV_MAX is less than the number of buffers
on the queue.
(buffer_flush_window) Incorporate logic from buffer_flush_vty.
Log an error message if there is a writev error.
(buffer_flush_available) Be more paranoid: check for case where
buffer is already empty. Use new ERRNO_IO_RETRY macro, and use
new enum for return codes. Simplify deletion logic (since it's
now a singly-linked list).
(buffer_write) New function for use with non-blocking I/O.
* vty.h: Replace the struct vty sb_buffer field with a fixed-size
(5-character) sb_buf field and an sb_len field, since using
a struct buffer was inappropriate for this task. Add some useful
comments about telnet window size negotiation.
* vty.c: Include <arpa/telnet.h> (no longer included by zebra.h).
Remove VTY_OBUF_SIZE (instead use buffer_new default size).
Make telnet_backward_char and telnet_space_char static const.
(vty_out) Replace buffer_write with buffer_put.
(vty_log_out) Check for I/O errors. If fatal, close the vty session.
Consolidate 3 separate writes into a single write call.
(vty_will_echo,vty_command,vty_next_line,vty_previous_line,
vty_end_config,vty_describe_fold,vty_clear_buf,vty_serv_sock_addrinfo,
vty_serv_sock_family,vty_serv_un,vty_use_backup_config,exec_timeout,
vty_config_write,vty_save_cwd) Fix scope to static.
(vty_new) Let buffer_new use its default buffer size.
(vty_write) Fix signature: 2nd arg should be const char *.
Replaced buffer_write with buffer_put.
(vty_telnet_option) Fix minor bug (window height or width greater than
255 was broken). Use sb_buf and sb_len instead of removed sb_buffer
(which was being used improperly).
(vty_read) On error, use ERRNO_IO_RETRY to decide whether it's fatal.
If the error is fatal, call buffer_reset so vty_close does not attempt
to flush the data. Use new sb_buf and sb_len instead of sb_buffer
to store the SB negotiation string.
(vty_flush) When vty->lines is 0, call buffer_flush_available instead
of buffer_flush_window. Look at the return code from buffer_flush
to detect I/O errors (and in that case, log an error message and
close the vty).
(vty_create) Fix scope to static. Initialize sb_len to 0 instead
of creating sb_buffer.
(vty_accept) Set socket nonblocking.
(vtysh_accept) Use new set_nonblocking function instead of calling
fcntl directly.
(vtysh_flush) New function called from vtysh_read (after command
execution) and from vtysh_write. This flushes the buffer
and reacts appropriately to the return code (by closing the vty
or scheduling further flushes).
(vtysh_read) Check whether error is fatal using ERRNO_IO_RETRY.
If not, just try again later. Otherwise, call buffer_reset before
calling vty_close (to avoid trying to flush the buffer in vty_close).
Fix logic to allow case where a command does not arrive atomically
in a single read call by checking for the terminating NUL char.
(vtysh_write) Use new vtysh_flush helper function.
(vty_close) No need to call buffer_empty, just call buffer_flush_all
in any case (it will check whether the buffer is empty).
Do not free sb_buffer (since it has been removed).
(vty_log_fixed) Use writev instead of write.
* zebra.h: Do not include <arpa/telnet.h>, since this is used only
by lib/vty.c.
2005-02-23 16:12:34 +01:00
|
|
|
/* IAC handling: was the last character received the
|
|
|
|
IAC (interpret-as-command) escape character (and therefore the next
|
|
|
|
character will be the command code)? Refer to Telnet RFC 854. */
|
2002-12-13 21:15:29 +01:00
|
|
|
unsigned char iac;
|
|
|
|
|
2005-02-23 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* buffer.h: Make the struct buffer and struct buffer_data structures
private by moving them inside buffer.c. Add comments for all
functions. Rename buffer_write as buffer_put (to be more consistent
with the buffer_putc and buffer_putstr functions). Declare a new
buffer_write function that is used to write data to a file descriptor
and/or add it to the buffer queue. Remove unused function
buffer_flush_vty_all. Create a new enum typedef buffer_status_t
to be used as the return code for all buffer_flush* functions
and buffer_write.
* buffer.c: The struct buffer and struct buffer_data declarations
are now private to this file. In conjunction with that, remove
some unnecessary fields: struct buffer (alloc, unused_head,
unused_tail, length), struct buffer_data (prev).
(buffer_data_new) Removed: functionality incorporated into buffer_add.
(buffer_data_free) Removed: use a macro BUFFER_DATA_FREE instead.
(buffer_new) Use calloc instead of malloc + memset(zero).
Supply an appropriate default size if the specified size is 0.
(buffer_free) Eliminate code duplication by calling buffer_reset to
free the contents of the buffer (and remove unused code related
to unused_head).
(buffer_empty,buffer_putc,buffer_putstr) Aesthetic change (make more
compact).
(buffer_reset) Use macro BUFFER_DATA_FREE. No need to set
alloc and length to 0 (these fields have been removed).
(buffer_add) Fix scope to be static. Call XMALLOC directly instead
of calling removed buffer_data_new function. Simplify the logic
(since it's now a singly-linked list instead of doubly-linked).
(buffer_write) Renamed to buffer_put. Change to void, since return
code of 1 was meaningless. No need to adjust length field, since
it has been removed.
(buffer_putw,buffer_flush,buffer_flush_vty_all,buffer_flush_vty)
Remove unused functions.
(buffer_flush_all) Rewrite using buffer_flush_available to eliminate
a possible failure mode if IOV_MAX is less than the number of buffers
on the queue.
(buffer_flush_window) Incorporate logic from buffer_flush_vty.
Log an error message if there is a writev error.
(buffer_flush_available) Be more paranoid: check for case where
buffer is already empty. Use new ERRNO_IO_RETRY macro, and use
new enum for return codes. Simplify deletion logic (since it's
now a singly-linked list).
(buffer_write) New function for use with non-blocking I/O.
* vty.h: Replace the struct vty sb_buffer field with a fixed-size
(5-character) sb_buf field and an sb_len field, since using
a struct buffer was inappropriate for this task. Add some useful
comments about telnet window size negotiation.
* vty.c: Include <arpa/telnet.h> (no longer included by zebra.h).
Remove VTY_OBUF_SIZE (instead use buffer_new default size).
Make telnet_backward_char and telnet_space_char static const.
(vty_out) Replace buffer_write with buffer_put.
(vty_log_out) Check for I/O errors. If fatal, close the vty session.
Consolidate 3 separate writes into a single write call.
(vty_will_echo,vty_command,vty_next_line,vty_previous_line,
vty_end_config,vty_describe_fold,vty_clear_buf,vty_serv_sock_addrinfo,
vty_serv_sock_family,vty_serv_un,vty_use_backup_config,exec_timeout,
vty_config_write,vty_save_cwd) Fix scope to static.
(vty_new) Let buffer_new use its default buffer size.
(vty_write) Fix signature: 2nd arg should be const char *.
Replaced buffer_write with buffer_put.
(vty_telnet_option) Fix minor bug (window height or width greater than
255 was broken). Use sb_buf and sb_len instead of removed sb_buffer
(which was being used improperly).
(vty_read) On error, use ERRNO_IO_RETRY to decide whether it's fatal.
If the error is fatal, call buffer_reset so vty_close does not attempt
to flush the data. Use new sb_buf and sb_len instead of sb_buffer
to store the SB negotiation string.
(vty_flush) When vty->lines is 0, call buffer_flush_available instead
of buffer_flush_window. Look at the return code from buffer_flush
to detect I/O errors (and in that case, log an error message and
close the vty).
(vty_create) Fix scope to static. Initialize sb_len to 0 instead
of creating sb_buffer.
(vty_accept) Set socket nonblocking.
(vtysh_accept) Use new set_nonblocking function instead of calling
fcntl directly.
(vtysh_flush) New function called from vtysh_read (after command
execution) and from vtysh_write. This flushes the buffer
and reacts appropriately to the return code (by closing the vty
or scheduling further flushes).
(vtysh_read) Check whether error is fatal using ERRNO_IO_RETRY.
If not, just try again later. Otherwise, call buffer_reset before
calling vty_close (to avoid trying to flush the buffer in vty_close).
Fix logic to allow case where a command does not arrive atomically
in a single read call by checking for the terminating NUL char.
(vtysh_write) Use new vtysh_flush helper function.
(vty_close) No need to call buffer_empty, just call buffer_flush_all
in any case (it will check whether the buffer is empty).
Do not free sb_buffer (since it has been removed).
(vty_log_fixed) Use writev instead of write.
* zebra.h: Do not include <arpa/telnet.h>, since this is used only
by lib/vty.c.
2005-02-23 16:12:34 +01:00
|
|
|
/* IAC SB (option subnegotiation) handling */
|
2002-12-13 21:15:29 +01:00
|
|
|
unsigned char iac_sb_in_progress;
|
2005-02-23 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* buffer.h: Make the struct buffer and struct buffer_data structures
private by moving them inside buffer.c. Add comments for all
functions. Rename buffer_write as buffer_put (to be more consistent
with the buffer_putc and buffer_putstr functions). Declare a new
buffer_write function that is used to write data to a file descriptor
and/or add it to the buffer queue. Remove unused function
buffer_flush_vty_all. Create a new enum typedef buffer_status_t
to be used as the return code for all buffer_flush* functions
and buffer_write.
* buffer.c: The struct buffer and struct buffer_data declarations
are now private to this file. In conjunction with that, remove
some unnecessary fields: struct buffer (alloc, unused_head,
unused_tail, length), struct buffer_data (prev).
(buffer_data_new) Removed: functionality incorporated into buffer_add.
(buffer_data_free) Removed: use a macro BUFFER_DATA_FREE instead.
(buffer_new) Use calloc instead of malloc + memset(zero).
Supply an appropriate default size if the specified size is 0.
(buffer_free) Eliminate code duplication by calling buffer_reset to
free the contents of the buffer (and remove unused code related
to unused_head).
(buffer_empty,buffer_putc,buffer_putstr) Aesthetic change (make more
compact).
(buffer_reset) Use macro BUFFER_DATA_FREE. No need to set
alloc and length to 0 (these fields have been removed).
(buffer_add) Fix scope to be static. Call XMALLOC directly instead
of calling removed buffer_data_new function. Simplify the logic
(since it's now a singly-linked list instead of doubly-linked).
(buffer_write) Renamed to buffer_put. Change to void, since return
code of 1 was meaningless. No need to adjust length field, since
it has been removed.
(buffer_putw,buffer_flush,buffer_flush_vty_all,buffer_flush_vty)
Remove unused functions.
(buffer_flush_all) Rewrite using buffer_flush_available to eliminate
a possible failure mode if IOV_MAX is less than the number of buffers
on the queue.
(buffer_flush_window) Incorporate logic from buffer_flush_vty.
Log an error message if there is a writev error.
(buffer_flush_available) Be more paranoid: check for case where
buffer is already empty. Use new ERRNO_IO_RETRY macro, and use
new enum for return codes. Simplify deletion logic (since it's
now a singly-linked list).
(buffer_write) New function for use with non-blocking I/O.
* vty.h: Replace the struct vty sb_buffer field with a fixed-size
(5-character) sb_buf field and an sb_len field, since using
a struct buffer was inappropriate for this task. Add some useful
comments about telnet window size negotiation.
* vty.c: Include <arpa/telnet.h> (no longer included by zebra.h).
Remove VTY_OBUF_SIZE (instead use buffer_new default size).
Make telnet_backward_char and telnet_space_char static const.
(vty_out) Replace buffer_write with buffer_put.
(vty_log_out) Check for I/O errors. If fatal, close the vty session.
Consolidate 3 separate writes into a single write call.
(vty_will_echo,vty_command,vty_next_line,vty_previous_line,
vty_end_config,vty_describe_fold,vty_clear_buf,vty_serv_sock_addrinfo,
vty_serv_sock_family,vty_serv_un,vty_use_backup_config,exec_timeout,
vty_config_write,vty_save_cwd) Fix scope to static.
(vty_new) Let buffer_new use its default buffer size.
(vty_write) Fix signature: 2nd arg should be const char *.
Replaced buffer_write with buffer_put.
(vty_telnet_option) Fix minor bug (window height or width greater than
255 was broken). Use sb_buf and sb_len instead of removed sb_buffer
(which was being used improperly).
(vty_read) On error, use ERRNO_IO_RETRY to decide whether it's fatal.
If the error is fatal, call buffer_reset so vty_close does not attempt
to flush the data. Use new sb_buf and sb_len instead of sb_buffer
to store the SB negotiation string.
(vty_flush) When vty->lines is 0, call buffer_flush_available instead
of buffer_flush_window. Look at the return code from buffer_flush
to detect I/O errors (and in that case, log an error message and
close the vty).
(vty_create) Fix scope to static. Initialize sb_len to 0 instead
of creating sb_buffer.
(vty_accept) Set socket nonblocking.
(vtysh_accept) Use new set_nonblocking function instead of calling
fcntl directly.
(vtysh_flush) New function called from vtysh_read (after command
execution) and from vtysh_write. This flushes the buffer
and reacts appropriately to the return code (by closing the vty
or scheduling further flushes).
(vtysh_read) Check whether error is fatal using ERRNO_IO_RETRY.
If not, just try again later. Otherwise, call buffer_reset before
calling vty_close (to avoid trying to flush the buffer in vty_close).
Fix logic to allow case where a command does not arrive atomically
in a single read call by checking for the terminating NUL char.
(vtysh_write) Use new vtysh_flush helper function.
(vty_close) No need to call buffer_empty, just call buffer_flush_all
in any case (it will check whether the buffer is empty).
Do not free sb_buffer (since it has been removed).
(vty_log_fixed) Use writev instead of write.
* zebra.h: Do not include <arpa/telnet.h>, since this is used only
by lib/vty.c.
2005-02-23 16:12:34 +01:00
|
|
|
/* At the moment, we care only about the NAWS (window size) negotiation,
|
|
|
|
and that requires just a 5-character buffer (RFC 1073):
|
|
|
|
<NAWS char> <16-bit width> <16-bit height> */
|
|
|
|
#define TELNET_NAWS_SB_LEN 5
|
|
|
|
unsigned char sb_buf[TELNET_NAWS_SB_LEN];
|
|
|
|
/* How many subnegotiation characters have we received? We just drop
|
|
|
|
those that do not fit in the buffer. */
|
|
|
|
size_t sb_len;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* Window width/height. */
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
|
|
|
|
/* Configure lines. */
|
|
|
|
int lines;
|
|
|
|
|
|
|
|
/* Read and write thread. */
|
2022-03-01 22:18:12 +01:00
|
|
|
struct event *t_read;
|
|
|
|
struct event *t_write;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* Timeout seconds and thread. */
|
|
|
|
unsigned long v_timeout;
|
2022-03-01 22:18:12 +01:00
|
|
|
struct event *t_timeout;
|
2012-04-10 16:57:23 +02:00
|
|
|
|
|
|
|
/* What address is this vty comming from. */
|
|
|
|
char address[SU_ADDRSTRLEN];
|
2010-02-05 09:48:45 +01:00
|
|
|
|
|
|
|
/* "frame" output. This is buffered and will be printed if some
|
|
|
|
* actual output follows, or will be discarded if the frame ends
|
|
|
|
* without any output. */
|
|
|
|
size_t frame_pos;
|
|
|
|
char frame[1024];
|
2023-03-08 23:26:38 +01:00
|
|
|
|
2023-05-04 05:49:16 +02:00
|
|
|
uint64_t mgmt_session_id; /* FE adapter identifies session w/ this */
|
|
|
|
uint64_t mgmt_client_id; /* FE vty client identifies w/ this ID */
|
2023-03-08 23:26:38 +01:00
|
|
|
uint64_t mgmt_req_id;
|
2023-05-19 07:29:40 +02:00
|
|
|
/* set when we have sent mgmtd a *REQ command in response to some vty
|
|
|
|
* CLI command and we are waiting on the reply so we can respond to the
|
|
|
|
* vty user. */
|
2023-03-08 23:26:38 +01:00
|
|
|
bool mgmt_req_pending;
|
|
|
|
bool mgmt_locked_candidate_ds;
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
|
|
|
|
2016-09-26 18:36:49 +02:00
|
|
|
static inline void vty_push_context(struct vty *vty, int node, uint64_t id)
|
|
|
|
{
|
|
|
|
vty->node = node;
|
|
|
|
vty->qobj_index = id;
|
|
|
|
}
|
|
|
|
|
2016-12-07 12:16:05 +01:00
|
|
|
/* note: VTY_PUSH_CONTEXT(..., NULL) doesn't work, since it will try to
|
|
|
|
* dereference "NULL->qobj_node.nid" */
|
2016-09-26 18:36:49 +02:00
|
|
|
#define VTY_PUSH_CONTEXT(nodeval, ptr) \
|
2016-12-07 17:30:16 +01:00
|
|
|
vty_push_context(vty, nodeval, QOBJ_ID_0SAFE(ptr))
|
2016-12-07 12:16:05 +01:00
|
|
|
#define VTY_PUSH_CONTEXT_NULL(nodeval) vty_push_context(vty, nodeval, 0ULL)
|
2016-09-27 16:51:58 +02:00
|
|
|
#define VTY_PUSH_CONTEXT_SUB(nodeval, ptr) \
|
|
|
|
do { \
|
|
|
|
vty->node = nodeval; \
|
|
|
|
/* qobj_index stays untouched */ \
|
2016-12-07 12:16:05 +01:00
|
|
|
vty->qobj_index_sub = QOBJ_ID_0SAFE(ptr); \
|
2016-09-27 16:51:58 +02:00
|
|
|
} while (0)
|
2016-09-26 18:36:49 +02:00
|
|
|
|
|
|
|
/* can return NULL if context is invalid! */
|
|
|
|
#define VTY_GET_CONTEXT(structname) \
|
|
|
|
QOBJ_GET_TYPESAFE(vty->qobj_index, structname)
|
2016-09-27 16:51:58 +02:00
|
|
|
#define VTY_GET_CONTEXT_SUB(structname) \
|
|
|
|
QOBJ_GET_TYPESAFE(vty->qobj_index_sub, structname)
|
2016-09-26 18:36:49 +02:00
|
|
|
|
|
|
|
/* will return if ptr is NULL. */
|
|
|
|
#define VTY_CHECK_CONTEXT(ptr) \
|
|
|
|
if (!ptr) { \
|
|
|
|
vty_out(vty, \
|
|
|
|
"Current configuration object was deleted " \
|
2017-07-13 20:17:06 +02:00
|
|
|
"by another process.\n"); \
|
2016-09-26 18:36:49 +02:00
|
|
|
return CMD_WARNING; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* struct structname *ptr = <context>; ptr will never be NULL. */
|
|
|
|
#define VTY_DECLVAR_CONTEXT(structname, ptr) \
|
|
|
|
struct structname *ptr = VTY_GET_CONTEXT(structname); \
|
|
|
|
VTY_CHECK_CONTEXT(ptr);
|
2016-09-27 16:51:58 +02:00
|
|
|
#define VTY_DECLVAR_CONTEXT_SUB(structname, ptr) \
|
|
|
|
struct structname *ptr = VTY_GET_CONTEXT_SUB(structname); \
|
|
|
|
VTY_CHECK_CONTEXT(ptr);
|
2017-08-04 01:34:17 +02:00
|
|
|
#define VTY_DECLVAR_INSTANCE_CONTEXT(structname, ptr) \
|
|
|
|
if (vty->qobj_index == 0) \
|
|
|
|
return CMD_NOT_MY_INSTANCE; \
|
|
|
|
struct structname *ptr = VTY_GET_CONTEXT(structname); \
|
|
|
|
VTY_CHECK_CONTEXT(ptr);
|
2016-09-26 18:36:49 +02:00
|
|
|
|
2022-04-28 11:06:20 +02:00
|
|
|
#define VTY_DECLVAR_CONTEXT_VRF(vrfptr) \
|
|
|
|
struct vrf *vrfptr; \
|
|
|
|
if (vty->node == CONFIG_NODE) \
|
|
|
|
vrfptr = vrf_lookup_by_id(VRF_DEFAULT); \
|
|
|
|
else \
|
|
|
|
vrfptr = VTY_GET_CONTEXT(vrf); \
|
|
|
|
VTY_CHECK_CONTEXT(vrfptr); \
|
|
|
|
MACRO_REQUIRE_SEMICOLON() /* end */
|
|
|
|
|
2017-12-07 20:31:48 +01:00
|
|
|
/* XPath macros. */
|
|
|
|
#define VTY_PUSH_XPATH(nodeval, value) \
|
|
|
|
do { \
|
|
|
|
if (vty->xpath_index >= VTY_MAXDEPTH) { \
|
|
|
|
vty_out(vty, "%% Reached maximum CLI depth (%u)\n", \
|
|
|
|
VTY_MAXDEPTH); \
|
|
|
|
return CMD_WARNING; \
|
|
|
|
} \
|
|
|
|
vty->node = nodeval; \
|
|
|
|
strlcpy(vty->xpath[vty->xpath_index], value, \
|
|
|
|
sizeof(vty->xpath[0])); \
|
|
|
|
vty->xpath_index++; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define VTY_CURR_XPATH vty->xpath[vty->xpath_index - 1]
|
|
|
|
|
|
|
|
#define VTY_CHECK_XPATH \
|
|
|
|
do { \
|
2023-05-09 15:19:24 +02:00
|
|
|
if (vty->type != VTY_FILE && !vty->private_config && \
|
|
|
|
vty->xpath_index > 0 && \
|
|
|
|
!yang_dnode_exists(vty->candidate_config->dnode, \
|
|
|
|
VTY_CURR_XPATH)) { \
|
2017-12-07 20:31:48 +01:00
|
|
|
vty_out(vty, \
|
|
|
|
"Current configuration object was deleted " \
|
|
|
|
"by another process.\n\n"); \
|
|
|
|
return CMD_WARNING; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
struct vty_arg {
|
|
|
|
const char *name;
|
|
|
|
const char *value;
|
|
|
|
const char **argv;
|
|
|
|
int argc;
|
|
|
|
};
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Integrated configuration file. */
|
2017-02-27 19:26:20 +01:00
|
|
|
#define INTEGRATE_DEFAULT_CONFIG "frr.conf"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* Default time out value */
|
|
|
|
#define VTY_TIMEOUT_DEFAULT 600
|
|
|
|
|
|
|
|
/* Vty read buffer size. */
|
|
|
|
#define VTY_READ_BUFSIZ 512
|
|
|
|
|
|
|
|
/* Directory separator. */
|
|
|
|
#ifndef DIRECTORY_SEP
|
|
|
|
#define DIRECTORY_SEP '/'
|
|
|
|
#endif /* DIRECTORY_SEP */
|
|
|
|
|
|
|
|
#ifndef IS_DIRECTORY_SEP
|
|
|
|
#define IS_DIRECTORY_SEP(c) ((c) == DIRECTORY_SEP)
|
|
|
|
#endif
|
|
|
|
|
2023-03-08 23:26:38 +01:00
|
|
|
extern struct nb_config *vty_mgmt_candidate_config;
|
2023-05-03 06:41:19 +02:00
|
|
|
extern bool vty_log_commands;
|
2023-03-08 23:26:38 +01:00
|
|
|
|
2023-05-09 15:19:24 +02:00
|
|
|
extern char const *const mgmt_daemons[];
|
|
|
|
extern uint mgmt_daemons_count;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Prototypes. */
|
2023-03-07 20:14:41 +01:00
|
|
|
extern void vty_init(struct event_loop *m, bool do_command_logging);
|
2005-05-06 Paul Jakma <paul@dishone.st>
* (general) extern and static'ification of functions in code and
header.
Cleanup any definitions with unspecified arguments.
Add casts for callback assignments where the callback is defined,
typically, as passing void *, but the function being assigned has
some other pointer type defined as its argument, as gcc complains
about casts from void * to X* via function arguments.
Fix some old K&R style function argument definitions.
Add noreturn gcc attribute to some functions, as appropriate.
Add unused gcc attribute to some functions (eg ones meant to help
while debugging)
Add guard defines to headers which were missing them.
* command.c: (install_node) add const qualifier, still doesnt shut
up the warning though, because of the double pointer.
(cmp_node) ditto
* keychain.c: (key_str2time) Add GET_LONG_RANGE() macro, derived
fromn vty.h ones to fix some of the (long) < 0 warnings.
* thread.c: (various) use thread_empty
(cpu_record_hash_key) should cast to uintptr_t, a stdint.h type
* vty.h: Add VTY_GET_IPV4_ADDRESS and VTY_GET_IPV4_PREFIX so they
removed from ospfd/ospf_vty.h
* zebra.h: Move definition of ZEBRA_PORT to here, to remove
dependence of lib on zebra/zserv.h
2005-05-06 23:25:49 +02:00
|
|
|
extern void vty_init_vtysh(void);
|
[bgpd] Stability fixes including bugs 397, 492
I've spent the last several weeks working on stability fixes to bgpd.
These patches fix all of the numerous crashes, assertion failures, memory
leaks and memory stomping I could find. Valgrind was used extensively.
Added new function bgp_exit() to help catch problems. If "debug bgp" is
configured and bgpd exits with status of 0, statistics on remaining
lib/memory.c allocations are printed to stderr. It is my hope that other
developers will use this to stay on top of memory issues.
Example questionable exit:
bgpd: memstats: Current memory utilization in module LIB:
bgpd: memstats: Link List : 6
bgpd: memstats: Link Node : 5
bgpd: memstats: Hash : 8
bgpd: memstats: Hash Bucket : 2
bgpd: memstats: Hash Index : 8
bgpd: memstats: Work queue : 3
bgpd: memstats: Work queue item : 2
bgpd: memstats: Work queue name string : 3
bgpd: memstats: Current memory utilization in module BGP:
bgpd: memstats: BGP instance : 1
bgpd: memstats: BGP peer : 1
bgpd: memstats: BGP peer hostname : 1
bgpd: memstats: BGP attribute : 1
bgpd: memstats: BGP extra attributes : 1
bgpd: memstats: BGP aspath : 1
bgpd: memstats: BGP aspath str : 1
bgpd: memstats: BGP table : 24
bgpd: memstats: BGP node : 1
bgpd: memstats: BGP route : 1
bgpd: memstats: BGP synchronise : 8
bgpd: memstats: BGP Process queue : 1
bgpd: memstats: BGP node clear queue : 1
bgpd: memstats: NOTE: If configuration exists, utilization may be expected.
Example clean exit:
bgpd: memstats: No remaining tracked memory utilization.
This patch fixes bug #397: "Invalid free in bgp_announce_check()".
This patch fixes bug #492: "SIGBUS in bgpd/bgp_route.c:
bgp_clear_route_node()".
My apologies for not separating out these changes into individual patches.
The complexity of doing so boggled what is left of my brain. I hope this
is all still useful to the community.
This code has been production tested, in non-route-server-client mode, on
a linux 32-bit box and a 64-bit box.
Release/reset functions, used by bgp_exit(), added to:
bgpd/bgp_attr.c,h
bgpd/bgp_community.c,h
bgpd/bgp_dump.c,h
bgpd/bgp_ecommunity.c,h
bgpd/bgp_filter.c,h
bgpd/bgp_nexthop.c,h
bgpd/bgp_route.c,h
lib/routemap.c,h
File by file analysis:
* bgpd/bgp_aspath.c: Prevent re-use of ashash after it is released.
* bgpd/bgp_attr.c: #if removed uncalled cluster_dup().
* bgpd/bgp_clist.c,h: Allow community_list_terminate() to be called from
bgp_exit().
* bgpd/bgp_filter.c: Fix aslist->name use without allocation check, and
also fix memory leak.
* bgpd/bgp_main.c: Created bgp_exit() exit routine. This function frees
allocations made as part of bgpd initialization and, to some extent,
configuration. If "debug bgp" is configured, memory stats are printed
as described above.
* bgpd/bgp_nexthop.c: zclient_new() already allocates stream for
ibuf/obuf, so bgp_scan_init() shouldn't do it too. Also, made it so
zlookup is global so bgp_exit() can use it.
* bgpd/bgp_packet.c: bgp_capability_msg_parse() call to bgp_clear_route()
adjusted to use new BGP_CLEAR_ROUTE_NORMAL flag.
* bgpd/bgp_route.h: Correct reference counter "lock" to be signed.
bgp_clear_route() now accepts a bgp_clear_route_type of either
BGP_CLEAR_ROUTE_NORMAL or BGP_CLEAR_ROUTE_MY_RSCLIENT.
* bgpd/bgp_route.c:
- bgp_process_rsclient(): attr was being zero'ed and then
bgp_attr_extra_free() was being called with it, even though it was
never filled with valid data.
- bgp_process_rsclient(): Make sure rsclient->group is not NULL before
use.
- bgp_processq_del(): Add call to bgp_table_unlock().
- bgp_process(): Add call to bgp_table_lock().
- bgp_update_rsclient(): memset clearing of new_attr not needed since
declarationw with "= { 0 }" does it. memset was already commented
out.
- bgp_update_rsclient(): Fix screwed up misleading indentation.
- bgp_withdraw_rsclient(): Fix screwed up misleading indentation.
- bgp_clear_route_node(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_node_queue_del(): Add call to bgp_table_unlock() and also
free struct bgp_clear_node_queue used for work item.
- bgp_clear_node_complete(): Do peer_unlock() after BGP_EVENT_ADD() in
case peer is released by peer_unlock() call.
- bgp_clear_route_table(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT. Use
struct bgp_clear_node_queue to supply data to worker. Add call to
bgp_table_lock().
- bgp_clear_route(): Add support for BGP_CLEAR_ROUTE_NORMAL or
BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_route_all(): Use BGP_CLEAR_ROUTE_NORMAL.
Bug 397 fixes:
- bgp_default_originate()
- bgp_announce_table()
* bgpd/bgp_table.h:
- struct bgp_table: Added reference count. Changed type of owner to be
"struct peer *" rather than "void *".
- struct bgp_node: Correct reference counter "lock" to be signed.
* bgpd/bgp_table.c:
- Added bgp_table reference counting.
- bgp_table_free(): Fixed cleanup code. Call peer_unlock() on owner if
set.
- bgp_unlock_node(): Added assertion.
- bgp_node_get(): Added call to bgp_lock_node() to code path that it was
missing from.
* bgpd/bgp_vty.c:
- peer_rsclient_set_vty(): Call peer_lock() as part of peer assignment
to owner. Handle failure gracefully.
- peer_rsclient_unset_vty(): Add call to bgp_clear_route() with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
* bgpd/bgp_zebra.c: Made it so zclient is global so bgp_exit() can use it.
* bgpd/bgpd.c:
- peer_lock(): Allow to be called when status is "Deleted".
- peer_deactivate(): Supply BGP_CLEAR_ROUTE_NORMAL purpose to
bgp_clear_route() call.
- peer_delete(): Common variable listnode pn. Fix bug in which rsclient
was only dealt with if not part of a peer group. Call
bgp_clear_route() for rsclient, if appropriate, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- peer_group_get(): Use XSTRDUP() instead of strdup() for conf->host.
- peer_group_bind(): Call bgp_clear_route() for rsclient, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- bgp_create(): Use XSTRDUP() instead of strdup() for peer_self->host.
- bgp_delete(): Delete peers before groups, rather than after. And then
rather than deleting rsclients, verify that there are none at this
point.
- bgp_unlock(): Add assertion.
- bgp_free(): Call bgp_table_finish() rather than doing XFREE() itself.
* lib/command.c,h: Compiler warning fixes. Add cmd_terminate(). Fixed
massive leak in install_element() in which cmd_make_descvec() was being
called more than once for the same cmd->strvec/string/doc.
* lib/log.c: Make closezlog() check fp before calling fclose().
* lib/memory.c: Catch when alloc count goes negative by using signed
counts. Correct #endif comment. Add log_memstats_stderr().
* lib/memory.h: Add log_memstats_stderr().
* lib/thread.c: thread->funcname was being accessed in thread_call() after
it had been freed. Rearranged things so that thread_call() frees
funcname. Also made it so thread_master_free() cleans up cpu_record.
* lib/vty.c,h: Use global command_cr. Add vty_terminate().
* lib/zclient.c,h: Re-enable zclient_free().
2009-07-18 07:44:03 +02:00
|
|
|
extern void vty_terminate(void);
|
2005-05-06 Paul Jakma <paul@dishone.st>
* (general) extern and static'ification of functions in code and
header.
Cleanup any definitions with unspecified arguments.
Add casts for callback assignments where the callback is defined,
typically, as passing void *, but the function being assigned has
some other pointer type defined as its argument, as gcc complains
about casts from void * to X* via function arguments.
Fix some old K&R style function argument definitions.
Add noreturn gcc attribute to some functions, as appropriate.
Add unused gcc attribute to some functions (eg ones meant to help
while debugging)
Add guard defines to headers which were missing them.
* command.c: (install_node) add const qualifier, still doesnt shut
up the warning though, because of the double pointer.
(cmp_node) ditto
* keychain.c: (key_str2time) Add GET_LONG_RANGE() macro, derived
fromn vty.h ones to fix some of the (long) < 0 warnings.
* thread.c: (various) use thread_empty
(cpu_record_hash_key) should cast to uintptr_t, a stdint.h type
* vty.h: Add VTY_GET_IPV4_ADDRESS and VTY_GET_IPV4_PREFIX so they
removed from ospfd/ospf_vty.h
* zebra.h: Move definition of ZEBRA_PORT to here, to remove
dependence of lib on zebra/zserv.h
2005-05-06 23:25:49 +02:00
|
|
|
extern void vty_reset(void);
|
|
|
|
extern struct vty *vty_new(void);
|
2017-06-01 16:02:23 +02:00
|
|
|
extern struct vty *vty_stdio(void (*atclose)(int isexit));
|
2010-02-05 09:48:45 +01:00
|
|
|
|
|
|
|
/* - vty_frame() output goes to a buffer (for context-begin markers)
|
|
|
|
* - vty_out() will first print this buffer, and clear it
|
|
|
|
* - vty_endframe() clears the buffer without printing it, and prints an
|
|
|
|
* extra string if the buffer was empty before (for context-end markers)
|
|
|
|
*/
|
2019-06-12 17:08:01 +02:00
|
|
|
extern int vty_out(struct vty *, const char *, ...) PRINTFRR(2, 3);
|
|
|
|
extern void vty_frame(struct vty *, const char *, ...) PRINTFRR(2, 3);
|
2010-02-05 09:48:45 +01:00
|
|
|
extern void vty_endframe(struct vty *, const char *);
|
2021-11-17 11:33:12 +01:00
|
|
|
extern bool vty_set_include(struct vty *vty, const char *regexp);
|
2021-11-17 11:39:00 +01:00
|
|
|
/* returns CMD_SUCCESS so you can do a one-line "return vty_json(...)"
|
|
|
|
* NULL check and json_object_free() is included.
|
2023-02-02 16:28:19 +01:00
|
|
|
*
|
|
|
|
* _no_pretty means do not add a bunch of newlines and dump the output
|
|
|
|
* as densely as possible.
|
2021-11-17 11:39:00 +01:00
|
|
|
*/
|
|
|
|
extern int vty_json(struct vty *vty, struct json_object *json);
|
2023-02-02 16:28:19 +01:00
|
|
|
extern int vty_json_no_pretty(struct vty *vty, struct json_object *json);
|
2023-02-07 23:29:54 +01:00
|
|
|
extern void vty_json_empty(struct vty *vty);
|
2019-12-04 00:17:50 +01:00
|
|
|
/* post fd to be passed to the vtysh client
|
|
|
|
* fd is owned by the VTY code after this and will be closed when done
|
|
|
|
*/
|
|
|
|
extern void vty_pass_fd(struct vty *vty, int fd);
|
|
|
|
|
2023-05-09 15:19:24 +02:00
|
|
|
extern FILE *vty_open_config(const char *config_file, char *config_default_dir);
|
2017-12-07 20:31:48 +01:00
|
|
|
extern bool vty_read_config(struct nb_config *config, const char *config_file,
|
|
|
|
char *config_default_dir);
|
2023-03-31 18:34:49 +02:00
|
|
|
extern void vty_read_file(struct nb_config *config, FILE *confp);
|
2023-05-09 15:19:24 +02:00
|
|
|
extern void vty_read_file_finish(struct vty *vty, struct nb_config *config);
|
2005-05-06 Paul Jakma <paul@dishone.st>
* (general) extern and static'ification of functions in code and
header.
Cleanup any definitions with unspecified arguments.
Add casts for callback assignments where the callback is defined,
typically, as passing void *, but the function being assigned has
some other pointer type defined as its argument, as gcc complains
about casts from void * to X* via function arguments.
Fix some old K&R style function argument definitions.
Add noreturn gcc attribute to some functions, as appropriate.
Add unused gcc attribute to some functions (eg ones meant to help
while debugging)
Add guard defines to headers which were missing them.
* command.c: (install_node) add const qualifier, still doesnt shut
up the warning though, because of the double pointer.
(cmp_node) ditto
* keychain.c: (key_str2time) Add GET_LONG_RANGE() macro, derived
fromn vty.h ones to fix some of the (long) < 0 warnings.
* thread.c: (various) use thread_empty
(cpu_record_hash_key) should cast to uintptr_t, a stdint.h type
* vty.h: Add VTY_GET_IPV4_ADDRESS and VTY_GET_IPV4_PREFIX so they
removed from ospfd/ospf_vty.h
* zebra.h: Move definition of ZEBRA_PORT to here, to remove
dependence of lib on zebra/zserv.h
2005-05-06 23:25:49 +02:00
|
|
|
extern void vty_time_print(struct vty *, int);
|
2023-05-19 10:25:57 +02:00
|
|
|
extern void vty_serv_start(const char *, unsigned short, const char *);
|
|
|
|
extern void vty_serv_stop(void);
|
2005-05-06 Paul Jakma <paul@dishone.st>
* (general) extern and static'ification of functions in code and
header.
Cleanup any definitions with unspecified arguments.
Add casts for callback assignments where the callback is defined,
typically, as passing void *, but the function being assigned has
some other pointer type defined as its argument, as gcc complains
about casts from void * to X* via function arguments.
Fix some old K&R style function argument definitions.
Add noreturn gcc attribute to some functions, as appropriate.
Add unused gcc attribute to some functions (eg ones meant to help
while debugging)
Add guard defines to headers which were missing them.
* command.c: (install_node) add const qualifier, still doesnt shut
up the warning though, because of the double pointer.
(cmp_node) ditto
* keychain.c: (key_str2time) Add GET_LONG_RANGE() macro, derived
fromn vty.h ones to fix some of the (long) < 0 warnings.
* thread.c: (various) use thread_empty
(cpu_record_hash_key) should cast to uintptr_t, a stdint.h type
* vty.h: Add VTY_GET_IPV4_ADDRESS and VTY_GET_IPV4_PREFIX so they
removed from ospfd/ospf_vty.h
* zebra.h: Move definition of ZEBRA_PORT to here, to remove
dependence of lib on zebra/zserv.h
2005-05-06 23:25:49 +02:00
|
|
|
extern void vty_close(struct vty *);
|
|
|
|
extern char *vty_get_cwd(void);
|
2021-06-16 13:07:30 +02:00
|
|
|
extern void vty_update_xpath(const char *oldpath, const char *newpath);
|
2018-11-26 19:47:22 +01:00
|
|
|
extern int vty_config_enter(struct vty *vty, bool private_config,
|
|
|
|
bool exclusive);
|
|
|
|
extern void vty_config_exit(struct vty *);
|
2018-09-09 00:03:19 +02:00
|
|
|
extern int vty_config_node_exit(struct vty *);
|
2005-05-06 Paul Jakma <paul@dishone.st>
* (general) extern and static'ification of functions in code and
header.
Cleanup any definitions with unspecified arguments.
Add casts for callback assignments where the callback is defined,
typically, as passing void *, but the function being assigned has
some other pointer type defined as its argument, as gcc complains
about casts from void * to X* via function arguments.
Fix some old K&R style function argument definitions.
Add noreturn gcc attribute to some functions, as appropriate.
Add unused gcc attribute to some functions (eg ones meant to help
while debugging)
Add guard defines to headers which were missing them.
* command.c: (install_node) add const qualifier, still doesnt shut
up the warning though, because of the double pointer.
(cmp_node) ditto
* keychain.c: (key_str2time) Add GET_LONG_RANGE() macro, derived
fromn vty.h ones to fix some of the (long) < 0 warnings.
* thread.c: (various) use thread_empty
(cpu_record_hash_key) should cast to uintptr_t, a stdint.h type
* vty.h: Add VTY_GET_IPV4_ADDRESS and VTY_GET_IPV4_PREFIX so they
removed from ospfd/ospf_vty.h
* zebra.h: Move definition of ZEBRA_PORT to here, to remove
dependence of lib on zebra/zserv.h
2005-05-06 23:25:49 +02:00
|
|
|
extern int vty_shell(struct vty *);
|
|
|
|
extern int vty_shell_serv(struct vty *);
|
|
|
|
extern void vty_hello(struct vty *);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-06-01 16:02:23 +02:00
|
|
|
/* ^Z / SIGTSTP handling */
|
|
|
|
extern void vty_stdio_suspend(void);
|
|
|
|
extern void vty_stdio_resume(void);
|
|
|
|
extern void vty_stdio_close(void);
|
|
|
|
|
2023-03-08 23:26:38 +01:00
|
|
|
extern void vty_init_mgmt_fe(void);
|
|
|
|
extern bool vty_mgmt_fe_enabled(void);
|
2023-05-19 07:29:40 +02:00
|
|
|
extern bool vty_mgmt_should_process_cli_apply_changes(struct vty *vty);
|
2023-05-09 15:19:24 +02:00
|
|
|
|
|
|
|
extern bool mgmt_vty_read_configs(void);
|
2023-03-08 23:26:38 +01:00
|
|
|
extern int vty_mgmt_send_config_data(struct vty *vty);
|
|
|
|
extern int vty_mgmt_send_commit_config(struct vty *vty, bool validate_only,
|
|
|
|
bool abort);
|
2023-03-20 20:07:44 +01:00
|
|
|
extern int vty_mgmt_send_get_config(struct vty *vty,
|
|
|
|
Mgmtd__DatastoreId datastore,
|
2023-03-08 23:26:38 +01:00
|
|
|
const char **xpath_list, int num_req);
|
|
|
|
extern int vty_mgmt_send_get_data(struct vty *vty, Mgmtd__DatastoreId datastore,
|
|
|
|
const char **xpath_list, int num_req);
|
|
|
|
extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id,
|
|
|
|
bool lock);
|
2023-03-14 11:36:06 +01:00
|
|
|
extern void vty_mgmt_resume_response(struct vty *vty, bool success);
|
|
|
|
|
|
|
|
static inline bool vty_needs_implicit_commit(struct vty *vty)
|
|
|
|
{
|
|
|
|
return (frr_get_cli_mode() == FRR_CLI_CLASSIC
|
2023-03-20 20:07:44 +01:00
|
|
|
? ((vty->pending_allowed || vty->no_implicit_commit)
|
|
|
|
? false
|
|
|
|
: true)
|
|
|
|
: false);
|
2023-03-14 11:36:06 +01:00
|
|
|
}
|
2023-03-08 23:26:38 +01:00
|
|
|
|
2019-02-07 23:10:31 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
#endif /* _ZEBRA_VTY_H */
|