diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:53:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:53:30 +0000 |
commit | 2c7cac91ed6e7db0f6937923d2b57f97dbdbc337 (patch) | |
tree | c05dc0f8e6aa3accc84e3e5cffc933ed94941383 /lib/vty.h | |
parent | Initial commit. (diff) | |
download | frr-2c7cac91ed6e7db0f6937923d2b57f97dbdbc337.tar.xz frr-2c7cac91ed6e7db0f6937923d2b57f97dbdbc337.zip |
Adding upstream version 8.4.4.upstream/8.4.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | lib/vty.h | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/lib/vty.h b/lib/vty.h new file mode 100644 index 0000000..0031ab6 --- /dev/null +++ b/lib/vty.h @@ -0,0 +1,387 @@ +/* Virtual terminal [aka TeletYpe] interface routine + * Copyright (C) 1997 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ZEBRA_VTY_H +#define _ZEBRA_VTY_H + +#include <sys/types.h> +#ifdef HAVE_LIBPCREPOSIX +#include <pcreposix.h> +#else +#include <regex.h> +#endif /* HAVE_LIBPCREPOSIX */ + +#include "thread.h" +#include "log.h" +#include "sockunion.h" +#include "qobj.h" +#include "compiler.h" +#include "northbound.h" +#include "zlog_live.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct json_object; + +#define VTY_BUFSIZ 4096 +#define VTY_MAXHIST 20 +#define VTY_MAXDEPTH 8 + +#define VTY_MAXCFGCHANGES 16 + +struct vty_error { + char error_buf[VTY_BUFSIZ]; + uint32_t line_num; +}; + +struct vty_cfg_change { + char xpath[XPATH_MAXLEN]; + enum nb_operation operation; + const char *value; +}; + +PREDECL_DLIST(vtys); + +/* VTY struct. */ +struct vty { + struct vtys_item itm; + + /* File descripter of this vty. */ + int fd; + + /* output FD, to support stdin/stdout combination */ + int wfd; + + /* File output, used for VTYSH only */ + FILE *of; + FILE *of_saved; + + /* whether we are using pager or not */ + bool is_paged; + + /* Is this vty connect to file or not */ + enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type; + + /* Node status of this vty */ + int node; + + /* Failure count */ + int fail; + + /* Output filer regex */ + bool filter; + regex_t include; + + /* Line buffer */ + struct buffer *lbuf; + + /* Output buffer. */ + struct buffer *obuf; + + /* Command input buffer */ + char *buf; + + /* Command input error buffer */ + struct list *error; + + /* 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; + + /* Changes enqueued to be applied in the candidate configuration. */ + size_t num_cfg_changes; + struct vty_cfg_change cfg_changes[VTY_MAXCFGCHANGES]; + + /* XPath of the current node */ + int xpath_index; + char xpath[VTY_MAXDEPTH][XPATH_MAXLEN]; + + /* In configure mode. */ + bool config; + + /* Private candidate configuration mode. */ + bool private_config; + + /* Candidate configuration. */ + struct nb_config *candidate_config; + + /* Base candidate configuration. */ + struct nb_config *candidate_config_base; + + /* Dynamic transaction information. */ + bool pending_allowed; + bool pending_commit; + char *pending_cmds_buf; + size_t pending_cmds_buflen; + size_t pending_cmds_bufpos; + + /* Confirmed-commit timeout and rollback configuration. */ + struct thread *t_confirmed_commit_timeout; + struct nb_config *confirmed_commit_rollback; + + /* qobj object ID (replacement for "index") */ + uint64_t qobj_index; + + /* qobj second-level object ID (replacement for "index_sub") */ + uint64_t qobj_index_sub; + + /* For escape character. */ + unsigned char escape; + + /* Current vty status. */ + 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]; + + /* live logging target / terminal monitor */ + struct zlog_live_cfg live_log; + + /* 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. */ + unsigned char iac; + + /* IAC SB (option subnegotiation) handling */ + unsigned char iac_sb_in_progress; +/* 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; + + /* Window width/height. */ + int width; + int height; + + /* Configure lines. */ + int lines; + + /* Read and write thread. */ + struct thread *t_read; + struct thread *t_write; + + /* Timeout seconds and thread. */ + unsigned long v_timeout; + struct thread *t_timeout; + + /* What address is this vty comming from. */ + char address[SU_ADDRSTRLEN]; + + /* "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]; +}; + +static inline void vty_push_context(struct vty *vty, int node, uint64_t id) +{ + vty->node = node; + vty->qobj_index = id; +} + +/* note: VTY_PUSH_CONTEXT(..., NULL) doesn't work, since it will try to + * dereference "NULL->qobj_node.nid" */ +#define VTY_PUSH_CONTEXT(nodeval, ptr) \ + vty_push_context(vty, nodeval, QOBJ_ID_0SAFE(ptr)) +#define VTY_PUSH_CONTEXT_NULL(nodeval) vty_push_context(vty, nodeval, 0ULL) +#define VTY_PUSH_CONTEXT_SUB(nodeval, ptr) \ + do { \ + vty->node = nodeval; \ + /* qobj_index stays untouched */ \ + vty->qobj_index_sub = QOBJ_ID_0SAFE(ptr); \ + } while (0) + +/* can return NULL if context is invalid! */ +#define VTY_GET_CONTEXT(structname) \ + QOBJ_GET_TYPESAFE(vty->qobj_index, structname) +#define VTY_GET_CONTEXT_SUB(structname) \ + QOBJ_GET_TYPESAFE(vty->qobj_index_sub, structname) + +/* will return if ptr is NULL. */ +#define VTY_CHECK_CONTEXT(ptr) \ + if (!ptr) { \ + vty_out(vty, \ + "Current configuration object was deleted " \ + "by another process.\n"); \ + 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); +#define VTY_DECLVAR_CONTEXT_SUB(structname, ptr) \ + struct structname *ptr = VTY_GET_CONTEXT_SUB(structname); \ + VTY_CHECK_CONTEXT(ptr); +#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); + +#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 */ + +/* 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 { \ + if (vty->type != VTY_FILE && !vty->private_config \ + && vty->xpath_index > 0 \ + && !yang_dnode_exists(vty->candidate_config->dnode, \ + VTY_CURR_XPATH)) { \ + vty_out(vty, \ + "Current configuration object was deleted " \ + "by another process.\n\n"); \ + return CMD_WARNING; \ + } \ + } while (0) + +struct vty_arg { + const char *name; + const char *value; + const char **argv; + int argc; +}; + +/* Integrated configuration file. */ +#define INTEGRATE_DEFAULT_CONFIG "frr.conf" + +/* 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 + +/* Prototypes. */ +extern void vty_init(struct thread_master *, bool do_command_logging); +extern void vty_init_vtysh(void); +extern void vty_terminate(void); +extern void vty_reset(void); +extern struct vty *vty_new(void); +extern struct vty *vty_stdio(void (*atclose)(int isexit)); + +/* - 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) + */ +extern int vty_out(struct vty *, const char *, ...) PRINTFRR(2, 3); +extern void vty_frame(struct vty *, const char *, ...) PRINTFRR(2, 3); +extern void vty_endframe(struct vty *, const char *); +extern bool vty_set_include(struct vty *vty, const char *regexp); +/* returns CMD_SUCCESS so you can do a one-line "return vty_json(...)" + * NULL check and json_object_free() is included. + * + * _no_pretty means do not add a bunch of newlines and dump the output + * as densely as possible. + */ +extern int vty_json(struct vty *vty, struct json_object *json); +extern int vty_json_no_pretty(struct vty *vty, struct json_object *json); + +/* 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); + +extern bool vty_read_config(struct nb_config *config, const char *config_file, + char *config_default_dir); +extern void vty_time_print(struct vty *, int); +extern void vty_serv_sock(const char *, unsigned short, const char *); +extern void vty_close(struct vty *); +extern char *vty_get_cwd(void); +extern void vty_update_xpath(const char *oldpath, const char *newpath); +extern int vty_config_enter(struct vty *vty, bool private_config, + bool exclusive); +extern void vty_config_exit(struct vty *); +extern int vty_config_node_exit(struct vty *); +extern int vty_shell(struct vty *); +extern int vty_shell_serv(struct vty *); +extern void vty_hello(struct vty *); + +/* ^Z / SIGTSTP handling */ +extern void vty_stdio_suspend(void); +extern void vty_stdio_resume(void); +extern void vty_stdio_close(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZEBRA_VTY_H */ |