Line data Source code
1 : /* Virtual terminal [aka TeletYpe] interface routine
2 : * Copyright (C) 1997 Kunihiro Ishiguro
3 : *
4 : * This file is part of GNU Zebra.
5 : *
6 : * GNU Zebra is free software; you can redistribute it and/or modify it
7 : * under the terms of the GNU General Public License as published by the
8 : * Free Software Foundation; either version 2, or (at your option) any
9 : * later version.
10 : *
11 : * GNU Zebra is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License along
17 : * with this program; see the file COPYING; if not, write to the Free Software
18 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : */
20 :
21 : #ifndef _ZEBRA_VTY_H
22 : #define _ZEBRA_VTY_H
23 :
24 : #include <sys/types.h>
25 : #ifdef HAVE_LIBPCRE2_POSIX
26 : #ifndef _FRR_PCRE2_POSIX
27 : #define _FRR_PCRE2_POSIX
28 : #include <pcre2posix.h>
29 : #endif /* _FRR_PCRE2_POSIX */
30 : #elif defined(HAVE_LIBPCREPOSIX)
31 : #include <pcreposix.h>
32 : #else
33 : #include <regex.h>
34 : #endif /* HAVE_LIBPCRE2_POSIX */
35 :
36 : #include "thread.h"
37 : #include "log.h"
38 : #include "sockunion.h"
39 : #include "qobj.h"
40 : #include "compiler.h"
41 : #include "northbound.h"
42 : #include "zlog_live.h"
43 :
44 : #ifdef __cplusplus
45 : extern "C" {
46 : #endif
47 :
48 : struct json_object;
49 :
50 : #define VTY_BUFSIZ 4096
51 : #define VTY_MAXHIST 20
52 : #define VTY_MAXDEPTH 8
53 :
54 : #define VTY_MAXCFGCHANGES 16
55 :
56 : struct vty_error {
57 : char error_buf[VTY_BUFSIZ];
58 : uint32_t line_num;
59 : };
60 :
61 : struct vty_cfg_change {
62 : char xpath[XPATH_MAXLEN];
63 : enum nb_operation operation;
64 : const char *value;
65 : };
66 :
67 : PREDECL_DLIST(vtys);
68 :
69 : /* VTY struct. */
70 : struct vty {
71 : struct vtys_item itm;
72 :
73 : /* File descripter of this vty. */
74 : int fd;
75 :
76 : /* output FD, to support stdin/stdout combination */
77 : int wfd;
78 :
79 : /* File output, used for VTYSH only */
80 : FILE *of;
81 : FILE *of_saved;
82 :
83 : /* whether we are using pager or not */
84 : bool is_paged;
85 :
86 : /* Is this vty connect to file or not */
87 : enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type;
88 :
89 : /* Node status of this vty */
90 : int node;
91 :
92 : /* Failure count */
93 : int fail;
94 :
95 : /* Output filer regex */
96 : bool filter;
97 : regex_t include;
98 :
99 : /* Line buffer */
100 : struct buffer *lbuf;
101 :
102 : /* Output buffer. */
103 : struct buffer *obuf;
104 :
105 : /* Command input buffer */
106 : char *buf;
107 :
108 : /* Command input error buffer */
109 : struct list *error;
110 :
111 : /* Command cursor point */
112 : int cp;
113 :
114 : /* Command length */
115 : int length;
116 :
117 : /* Command max length. */
118 : int max;
119 :
120 : /* Histry of command */
121 : char *hist[VTY_MAXHIST];
122 :
123 : /* History lookup current point */
124 : int hp;
125 :
126 : /* History insert end point */
127 : int hindex;
128 :
129 : /* Changes enqueued to be applied in the candidate configuration. */
130 : size_t num_cfg_changes;
131 : struct vty_cfg_change cfg_changes[VTY_MAXCFGCHANGES];
132 :
133 : /* XPath of the current node */
134 : int xpath_index;
135 : char xpath[VTY_MAXDEPTH][XPATH_MAXLEN];
136 :
137 : /* In configure mode. */
138 : bool config;
139 :
140 : /* Private candidate configuration mode. */
141 : bool private_config;
142 :
143 : /* Candidate configuration. */
144 : struct nb_config *candidate_config;
145 :
146 : /* Base candidate configuration. */
147 : struct nb_config *candidate_config_base;
148 :
149 : /* Dynamic transaction information. */
150 : bool pending_allowed;
151 : bool pending_commit;
152 : char *pending_cmds_buf;
153 : size_t pending_cmds_buflen;
154 : size_t pending_cmds_bufpos;
155 :
156 : /* Confirmed-commit timeout and rollback configuration. */
157 : struct thread *t_confirmed_commit_timeout;
158 : struct nb_config *confirmed_commit_rollback;
159 :
160 : /* qobj object ID (replacement for "index") */
161 : uint64_t qobj_index;
162 :
163 : /* qobj second-level object ID (replacement for "index_sub") */
164 : uint64_t qobj_index_sub;
165 :
166 : /* For escape character. */
167 : unsigned char escape;
168 :
169 : /* Current vty status. */
170 : enum {
171 : VTY_NORMAL,
172 : VTY_CLOSE,
173 : VTY_MORE,
174 : VTY_MORELINE,
175 : VTY_PASSFD,
176 : } status;
177 :
178 : /* vtysh socket/fd passing (for terminal monitor) */
179 : int pass_fd;
180 :
181 : /* CLI command return value (likely CMD_SUCCESS) when pass_fd != -1 */
182 : uint8_t pass_fd_status[4];
183 :
184 : /* live logging target / terminal monitor */
185 : struct zlog_live_cfg live_log;
186 :
187 : /* IAC handling: was the last character received the
188 : IAC (interpret-as-command) escape character (and therefore the next
189 : character will be the command code)? Refer to Telnet RFC 854. */
190 : unsigned char iac;
191 :
192 : /* IAC SB (option subnegotiation) handling */
193 : unsigned char iac_sb_in_progress;
194 : /* At the moment, we care only about the NAWS (window size) negotiation,
195 : and that requires just a 5-character buffer (RFC 1073):
196 : <NAWS char> <16-bit width> <16-bit height> */
197 : #define TELNET_NAWS_SB_LEN 5
198 : unsigned char sb_buf[TELNET_NAWS_SB_LEN];
199 : /* How many subnegotiation characters have we received? We just drop
200 : those that do not fit in the buffer. */
201 : size_t sb_len;
202 :
203 : /* Window width/height. */
204 : int width;
205 : int height;
206 :
207 : /* Configure lines. */
208 : int lines;
209 :
210 : /* Read and write thread. */
211 : struct thread *t_read;
212 : struct thread *t_write;
213 :
214 : /* Timeout seconds and thread. */
215 : unsigned long v_timeout;
216 : struct thread *t_timeout;
217 :
218 : /* What address is this vty comming from. */
219 : char address[SU_ADDRSTRLEN];
220 :
221 : /* "frame" output. This is buffered and will be printed if some
222 : * actual output follows, or will be discarded if the frame ends
223 : * without any output. */
224 : size_t frame_pos;
225 : char frame[1024];
226 : };
227 :
228 26 : static inline void vty_push_context(struct vty *vty, int node, uint64_t id)
229 : {
230 26 : vty->node = node;
231 26 : vty->qobj_index = id;
232 18 : }
233 :
234 : /* note: VTY_PUSH_CONTEXT(..., NULL) doesn't work, since it will try to
235 : * dereference "NULL->qobj_node.nid" */
236 : #define VTY_PUSH_CONTEXT(nodeval, ptr) \
237 : vty_push_context(vty, nodeval, QOBJ_ID_0SAFE(ptr))
238 : #define VTY_PUSH_CONTEXT_NULL(nodeval) vty_push_context(vty, nodeval, 0ULL)
239 : #define VTY_PUSH_CONTEXT_SUB(nodeval, ptr) \
240 : do { \
241 : vty->node = nodeval; \
242 : /* qobj_index stays untouched */ \
243 : vty->qobj_index_sub = QOBJ_ID_0SAFE(ptr); \
244 : } while (0)
245 :
246 : /* can return NULL if context is invalid! */
247 : #define VTY_GET_CONTEXT(structname) \
248 : QOBJ_GET_TYPESAFE(vty->qobj_index, structname)
249 : #define VTY_GET_CONTEXT_SUB(structname) \
250 : QOBJ_GET_TYPESAFE(vty->qobj_index_sub, structname)
251 :
252 : /* will return if ptr is NULL. */
253 : #define VTY_CHECK_CONTEXT(ptr) \
254 : if (!ptr) { \
255 : vty_out(vty, \
256 : "Current configuration object was deleted " \
257 : "by another process.\n"); \
258 : return CMD_WARNING; \
259 : }
260 :
261 : /* struct structname *ptr = <context>; ptr will never be NULL. */
262 : #define VTY_DECLVAR_CONTEXT(structname, ptr) \
263 : struct structname *ptr = VTY_GET_CONTEXT(structname); \
264 : VTY_CHECK_CONTEXT(ptr);
265 : #define VTY_DECLVAR_CONTEXT_SUB(structname, ptr) \
266 : struct structname *ptr = VTY_GET_CONTEXT_SUB(structname); \
267 : VTY_CHECK_CONTEXT(ptr);
268 : #define VTY_DECLVAR_INSTANCE_CONTEXT(structname, ptr) \
269 : if (vty->qobj_index == 0) \
270 : return CMD_NOT_MY_INSTANCE; \
271 : struct structname *ptr = VTY_GET_CONTEXT(structname); \
272 : VTY_CHECK_CONTEXT(ptr);
273 :
274 : #define VTY_DECLVAR_CONTEXT_VRF(vrfptr) \
275 : struct vrf *vrfptr; \
276 : if (vty->node == CONFIG_NODE) \
277 : vrfptr = vrf_lookup_by_id(VRF_DEFAULT); \
278 : else \
279 : vrfptr = VTY_GET_CONTEXT(vrf); \
280 : VTY_CHECK_CONTEXT(vrfptr); \
281 : MACRO_REQUIRE_SEMICOLON() /* end */
282 :
283 : /* XPath macros. */
284 : #define VTY_PUSH_XPATH(nodeval, value) \
285 : do { \
286 : if (vty->xpath_index >= VTY_MAXDEPTH) { \
287 : vty_out(vty, "%% Reached maximum CLI depth (%u)\n", \
288 : VTY_MAXDEPTH); \
289 : return CMD_WARNING; \
290 : } \
291 : vty->node = nodeval; \
292 : strlcpy(vty->xpath[vty->xpath_index], value, \
293 : sizeof(vty->xpath[0])); \
294 : vty->xpath_index++; \
295 : } while (0)
296 :
297 : #define VTY_CURR_XPATH vty->xpath[vty->xpath_index - 1]
298 :
299 : #define VTY_CHECK_XPATH \
300 : do { \
301 : if (vty->type != VTY_FILE && !vty->private_config \
302 : && vty->xpath_index > 0 \
303 : && !yang_dnode_exists(vty->candidate_config->dnode, \
304 : VTY_CURR_XPATH)) { \
305 : vty_out(vty, \
306 : "Current configuration object was deleted " \
307 : "by another process.\n\n"); \
308 : return CMD_WARNING; \
309 : } \
310 : } while (0)
311 :
312 : struct vty_arg {
313 : const char *name;
314 : const char *value;
315 : const char **argv;
316 : int argc;
317 : };
318 :
319 : /* Integrated configuration file. */
320 : #define INTEGRATE_DEFAULT_CONFIG "frr.conf"
321 :
322 : /* Default time out value */
323 : #define VTY_TIMEOUT_DEFAULT 600
324 :
325 : /* Vty read buffer size. */
326 : #define VTY_READ_BUFSIZ 512
327 :
328 : /* Directory separator. */
329 : #ifndef DIRECTORY_SEP
330 : #define DIRECTORY_SEP '/'
331 : #endif /* DIRECTORY_SEP */
332 :
333 : #ifndef IS_DIRECTORY_SEP
334 : #define IS_DIRECTORY_SEP(c) ((c) == DIRECTORY_SEP)
335 : #endif
336 :
337 : /* Prototypes. */
338 : extern void vty_init(struct thread_master *, bool do_command_logging);
339 : extern void vty_init_vtysh(void);
340 : extern void vty_terminate(void);
341 : extern void vty_reset(void);
342 : extern struct vty *vty_new(void);
343 : extern struct vty *vty_stdio(void (*atclose)(int isexit));
344 :
345 : /* - vty_frame() output goes to a buffer (for context-begin markers)
346 : * - vty_out() will first print this buffer, and clear it
347 : * - vty_endframe() clears the buffer without printing it, and prints an
348 : * extra string if the buffer was empty before (for context-end markers)
349 : */
350 : extern int vty_out(struct vty *, const char *, ...) PRINTFRR(2, 3);
351 : extern void vty_frame(struct vty *, const char *, ...) PRINTFRR(2, 3);
352 : extern void vty_endframe(struct vty *, const char *);
353 : extern bool vty_set_include(struct vty *vty, const char *regexp);
354 : /* returns CMD_SUCCESS so you can do a one-line "return vty_json(...)"
355 : * NULL check and json_object_free() is included.
356 : *
357 : * _no_pretty means do not add a bunch of newlines and dump the output
358 : * as densely as possible.
359 : */
360 : extern int vty_json(struct vty *vty, struct json_object *json);
361 : extern int vty_json_no_pretty(struct vty *vty, struct json_object *json);
362 :
363 : /* post fd to be passed to the vtysh client
364 : * fd is owned by the VTY code after this and will be closed when done
365 : */
366 : extern void vty_pass_fd(struct vty *vty, int fd);
367 :
368 : extern bool vty_read_config(struct nb_config *config, const char *config_file,
369 : char *config_default_dir);
370 : extern void vty_time_print(struct vty *, int);
371 : extern void vty_serv_sock(const char *, unsigned short, const char *);
372 : extern void vty_close(struct vty *);
373 : extern char *vty_get_cwd(void);
374 : extern void vty_update_xpath(const char *oldpath, const char *newpath);
375 : extern int vty_config_enter(struct vty *vty, bool private_config,
376 : bool exclusive);
377 : extern void vty_config_exit(struct vty *);
378 : extern int vty_config_node_exit(struct vty *);
379 : extern int vty_shell(struct vty *);
380 : extern int vty_shell_serv(struct vty *);
381 : extern void vty_hello(struct vty *);
382 :
383 : /* ^Z / SIGTSTP handling */
384 : extern void vty_stdio_suspend(void);
385 : extern void vty_stdio_resume(void);
386 : extern void vty_stdio_close(void);
387 :
388 : #ifdef __cplusplus
389 : }
390 : #endif
391 :
392 : #endif /* _ZEBRA_VTY_H */
|