#include "frrstr.h"
#include "lib_errors.h"
#include "northbound_cli.h"
+#include "printfrr.h"
#include <arpa/telnet.h>
#include <termios.h>
+#ifndef VTYSH_EXTRACT_PL
+#include "lib/vty_clippy.c"
+#endif
+
DEFINE_MTYPE_STATIC(LIB, VTY, "VTY")
DEFINE_MTYPE_STATIC(LIB, VTY_OUT_BUF, "VTY output buffer")
DEFINE_MTYPE_STATIC(LIB, VTY_HIST, "VTY history")
static vector Vvty_serv_thread;
/* Current directory. */
-char *vty_cwd = NULL;
+static char vty_cwd[MAXPATHLEN];
/* Login password check. */
static int no_password_check = 0;
/* Integrated configuration file path */
static char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
-static int do_log_commands = 0;
+static bool do_log_commands;
+static bool do_log_commands_perm;
void vty_frame(struct vty *vty, const char *format, ...)
{
va_list args;
va_start(args, format);
- vsnprintf(vty->frame + vty->frame_pos,
- sizeof(vty->frame) - vty->frame_pos, format, args);
+ vsnprintfrr(vty->frame + vty->frame_pos,
+ sizeof(vty->frame) - vty->frame_pos, format, args);
vty->frame_pos = strlen(vty->frame);
va_end(args);
}
int vty_out(struct vty *vty, const char *format, ...)
{
va_list args;
- int len = 0;
- int size = 1024;
+ ssize_t len;
char buf[1024];
char *p = NULL;
char *filtered;
vty_out(vty, "%s", vty->frame);
}
- /* Try to write to initial buffer. */
va_start(args, format);
- len = vsnprintf(buf, sizeof(buf), format, args);
+ p = vasnprintfrr(MTYPE_VTY_OUT_BUF, buf, sizeof(buf), format, args);
va_end(args);
- /* Initial buffer is not enough. */
- if (len < 0 || len >= size) {
- while (1) {
- if (len > -1)
- size = len + 1;
- else
- size = size * 2;
-
- p = XREALLOC(MTYPE_VTY_OUT_BUF, p, size);
- if (!p)
- return -1;
-
- va_start(args, format);
- len = vsnprintf(p, size, format, args);
- va_end(args);
-
- if (len > -1 && len < size)
- break;
- }
- }
-
- /* When initial buffer is enough to store all output. */
- if (!p)
- p = buf;
+ len = strlen(p);
/* filter buffer */
if (vty->filter) {
}
static int vty_log_out(struct vty *vty, const char *level,
- const char *proto_str, const char *format,
- struct timestamp_control *ctl, va_list va)
+ const char *proto_str, const char *msg,
+ struct timestamp_control *ctl)
{
int ret;
int len;
if ((ret < 0) || ((size_t)(len += ret) >= sizeof(buf)))
return -1;
- if (((ret = vsnprintf(buf + len, sizeof(buf) - len, format, va)) < 0)
+ if (((ret = snprintf(buf + len, sizeof(buf) - len, "%s", msg)) < 0)
|| ((size_t)((len += ret) + 2) > sizeof(buf)))
return -1;
/* work backwards to ignore trailling isspace()
*/
for (s = buf + strlen(buf);
- (s > buf) && isspace((int)*(s - 1)); s--)
+ (s > buf) && isspace((unsigned char)s[-1]);
+ s--)
;
*s = '\0';
vty_out(vty, "%s\n", buf);
vty_out(vty, "MOTD file not found\n");
} else if (host.motd)
vty_out(vty, "%s", host.motd);
+
+#if CONFDATE > 20200901
+ CPP_NOTICE("Please remove solaris code from system as it is deprecated");
+#endif
+#ifdef SUNOS_5
+ zlog_warn("If you are using FRR on Solaris, the FRR developers would love to hear from you\n");
+ zlog_warn("Please send email to dev@lists.frrouting.org about this message\n");
+ zlog_warn("We are considering deprecating Solaris and want to find users of Solaris systems\n");
+#endif
}
/* Put out prompt and wait input from user. */
cp = buf;
if (cp != NULL) {
/* Skip white spaces. */
- while (isspace((int)*cp) && *cp != '\0')
+ while (isspace((unsigned char)*cp) && *cp != '\0')
cp++;
}
if (cp != NULL && *cp != '\0') {
return;
/* In case of 'help \t'. */
- if (isspace((int)vty->buf[vty->length - 1]))
+ if (isspace((unsigned char)vty->buf[vty->length - 1]))
vector_set(vline, NULL);
matched = cmd_complete_command(vline, vty, &ret);
if (pos == 0)
break;
- strncpy(buf, p, pos);
+ memcpy(buf, p, pos);
buf[pos] = '\0';
vty_out(vty, " %-*s %s\n", cmd_width, cmd, buf);
if (vline == NULL) {
vline = vector_init(1);
vector_set(vline, NULL);
- } else if (isspace((int)vty->buf[vty->length - 1]))
+ } else if (isspace((unsigned char)vty->buf[vty->length - 1]))
vector_set(vline, NULL);
describe = cmd_describe_command(vline, vty, &ret);
int vty_sock = THREAD_FD(thread);
struct vty *vty = THREAD_ARG(thread);
- vty->t_read = NULL;
/* Read raw data from socket */
if ((nbytes = read(vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) {
int vty_sock = THREAD_FD(thread);
struct vty *vty = THREAD_ARG(thread);
- vty->t_write = NULL;
-
/* Tempolary disable read thread. */
- if ((vty->lines == 0) && vty->t_read) {
- thread_cancel(vty->t_read);
- vty->t_read = NULL;
- }
+ if (vty->lines == 0)
+ THREAD_OFF(vty->t_read);
/* Function execution continue. */
erase = ((vty->status == VTY_MORE || vty->status == VTY_MORELINE));
if (!stdio_vty)
return;
- if (stdio_vty->t_write)
- thread_cancel(stdio_vty->t_write);
- if (stdio_vty->t_read)
- thread_cancel(stdio_vty->t_read);
- if (stdio_vty->t_timeout)
- thread_cancel(stdio_vty->t_timeout);
+ THREAD_OFF(stdio_vty->t_write);
+ THREAD_OFF(stdio_vty->t_read);
+ THREAD_OFF(stdio_vty->t_timeout);
if (stdio_termios)
tcsetattr(0, TCSANOW, &stdio_orig_termios);
sock = THREAD_FD(thread);
vty = THREAD_ARG(thread);
- vty->t_read = NULL;
if ((nbytes = read(sock, buf, VTY_READ_BUFSIZ)) <= 0) {
if (nbytes < 0) {
{
struct vty *vty = THREAD_ARG(thread);
- vty->t_write = NULL;
vtysh_flush(vty);
return 0;
}
bool was_stdio = false;
/* Cancel threads.*/
- if (vty->t_read)
- thread_cancel(vty->t_read);
- if (vty->t_write)
- thread_cancel(vty->t_write);
- if (vty->t_timeout)
- thread_cancel(vty->t_timeout);
+ THREAD_OFF(vty->t_read);
+ THREAD_OFF(vty->t_write);
+ THREAD_OFF(vty->t_timeout);
/* Flush buffer. */
buffer_flush_all(vty->obuf, vty->wfd);
struct vty *vty;
vty = THREAD_ARG(thread);
- vty->t_timeout = NULL;
vty->v_timeout = 0;
/* Clear buffer*/
vty->wfd = STDERR_FILENO;
vty->type = VTY_FILE;
vty->node = CONFIG_NODE;
+ vty->config = true;
if (config)
vty->candidate_config = config;
else {
* Automatically commit the candidate configuration after
* reading the configuration file.
*/
- if (config == NULL && vty->candidate_config
- && frr_get_cli_mode() == FRR_CLI_TRANSACTIONAL) {
+ if (config == NULL) {
ret = nb_candidate_commit(vty->candidate_config, NB_CLIENT_CLI,
vty, true, "Read configuration file",
NULL);
}
/* Small utility function which output log to the VTY. */
-void vty_log(const char *level, const char *proto_str, const char *format,
- struct timestamp_control *ctl, va_list va)
+void vty_log(const char *level, const char *proto_str, const char *msg,
+ struct timestamp_control *ctl)
{
unsigned int i;
struct vty *vty;
for (i = 0; i < vector_active(vtyvec); i++)
if ((vty = vector_slot(vtyvec, i)) != NULL)
- if (vty->monitor) {
- va_list ac;
- va_copy(ac, va);
- vty_log_out(vty, level, proto_str, format, ctl,
- ac);
- va_end(ac);
- }
+ if (vty->monitor)
+ vty_log_out(vty, level, proto_str, msg, ctl);
}
/* Async-signal-safe version of vty_log for fixed strings. */
vty->private_config = private_config;
vty->xpath_index = 0;
- pthread_rwlock_rdlock(&running_config->lock);
- {
- if (private_config) {
- vty->candidate_config = nb_config_dup(running_config);
+ if (private_config) {
+ vty->candidate_config = nb_config_dup(running_config);
+ vty->candidate_config_base = nb_config_dup(running_config);
+ vty_out(vty,
+ "Warning: uncommitted changes will be discarded on exit.\n\n");
+ } else {
+ vty->candidate_config = vty_shared_candidate_config;
+ if (frr_get_cli_mode() == FRR_CLI_TRANSACTIONAL)
vty->candidate_config_base =
nb_config_dup(running_config);
- vty_out(vty,
- "Warning: uncommitted changes will be discarded on exit.\n\n");
- } else {
- vty->candidate_config = vty_shared_candidate_config;
- if (frr_get_cli_mode() == FRR_CLI_TRANSACTIONAL)
- vty->candidate_config_base =
- nb_config_dup(running_config);
- }
}
- pthread_rwlock_unlock(&running_config->lock);
return CMD_SUCCESS;
}
vector_set_index(Vvty_serv_thread, sock, vty_serv_thread);
break;
case VTYSH_READ:
- vty->t_read = NULL;
thread_add_read(vty_master, vtysh_read, vty, sock,
&vty->t_read);
break;
case VTYSH_WRITE:
- vty->t_write = NULL;
thread_add_write(vty_master, vtysh_write, vty, sock,
&vty->t_write);
break;
#endif /* VTYSH */
case VTY_READ:
- vty->t_read = NULL;
thread_add_read(vty_master, vty_read, vty, sock, &vty->t_read);
/* Time out treatment. */
if (vty->v_timeout) {
- if (vty->t_timeout)
- thread_cancel(vty->t_timeout);
- vty->t_timeout = NULL;
+ THREAD_OFF(vty->t_timeout);
thread_add_timer(vty_master, vty_timeout, vty,
vty->v_timeout, &vty->t_timeout);
}
&vty->t_write);
break;
case VTY_TIMEOUT_RESET:
- if (vty->t_timeout) {
- thread_cancel(vty->t_timeout);
- vty->t_timeout = NULL;
- }
- if (vty->v_timeout) {
- vty->t_timeout = NULL;
+ THREAD_OFF(vty->t_timeout);
+ if (vty->v_timeout)
thread_add_timer(vty_master, vty_timeout, vty,
vty->v_timeout, &vty->t_timeout);
- }
break;
}
}
}
/* vty login. */
-DEFUN (log_commands,
+DEFPY (log_commands,
log_commands_cmd,
- "log commands",
+ "[no] log commands",
+ NO_STR
"Logging control\n"
- "Log all commands (can't be unset without restart)\n")
+ "Log all commands\n")
{
- do_log_commands = 1;
+ if (no) {
+ if (do_log_commands_perm) {
+ vty_out(vty,
+ "Daemon started with permanent logging turned on for commands, ignoring\n");
+ return CMD_WARNING;
+ }
+
+ do_log_commands = false;
+ } else
+ do_log_commands = true;
+
return CMD_SUCCESS;
}
for (i = 0; i < vector_active(Vvty_serv_thread); i++)
if ((vty_serv_thread = vector_slot(Vvty_serv_thread, i))
!= NULL) {
- thread_cancel(vty_serv_thread);
+ THREAD_OFF(vty_serv_thread);
vector_slot(Vvty_serv_thread, i) = NULL;
close(i);
}
vty_timeout_val = VTY_TIMEOUT_DEFAULT;
- if (vty_accesslist_name) {
- XFREE(MTYPE_VTY, vty_accesslist_name);
- vty_accesslist_name = NULL;
- }
-
- if (vty_ipv6_accesslist_name) {
- XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
- vty_ipv6_accesslist_name = NULL;
- }
+ XFREE(MTYPE_VTY, vty_accesslist_name);
+ XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
}
static void vty_save_cwd(void)
{
- char cwd[MAXPATHLEN];
char *c;
- c = getcwd(cwd, MAXPATHLEN);
+ c = getcwd(vty_cwd, sizeof(vty_cwd));
if (!c) {
/*
SYSCONFDIR, errno);
exit(-1);
}
- if (getcwd(cwd, MAXPATHLEN) == NULL) {
+ if (getcwd(vty_cwd, sizeof(vty_cwd)) == NULL) {
flog_err_sys(EC_LIB_SYSTEM_CALL,
"Failure to getcwd, errno: %d", errno);
exit(-1);
}
}
-
- size_t vty_cwd_sz = strlen(cwd) + 1;
- vty_cwd = XMALLOC(MTYPE_TMP, vty_cwd_sz);
- strlcpy(vty_cwd, cwd, vty_cwd_sz);
}
char *vty_get_cwd(void)
}
/* Install vty's own commands like `who' command. */
-void vty_init(struct thread_master *master_thread)
+void vty_init(struct thread_master *master_thread, bool do_command_logging)
{
/* For further configuration read, preserve current directory. */
vty_save_cwd();
install_element(CONFIG_NODE, &no_service_advanced_vty_cmd);
install_element(CONFIG_NODE, &show_history_cmd);
install_element(CONFIG_NODE, &log_commands_cmd);
+
+ if (do_command_logging) {
+ do_log_commands = true;
+ do_log_commands_perm = true;
+ }
+
install_element(ENABLE_NODE, &terminal_monitor_cmd);
install_element(ENABLE_NODE, &terminal_no_monitor_cmd);
install_element(ENABLE_NODE, &no_terminal_monitor_cmd);
void vty_terminate(void)
{
- XFREE(MTYPE_TMP, vty_cwd);
+ memset(vty_cwd, 0x00, sizeof(vty_cwd));
if (vtyvec && Vvty_serv_thread) {
vty_reset();