]> git.proxmox.com Git - mirror_frr.git/blob - lib/vty.h
Merge remote-tracking branch 'origin/cmaster' into cmaster-next
[mirror_frr.git] / lib / vty.h
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
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #ifndef _ZEBRA_VTY_H
22 #define _ZEBRA_VTY_H
23
24 #include "thread.h"
25 #include "log.h"
26 #include "sockunion.h"
27 #include "qobj.h"
28
29 #define VTY_BUFSIZ 512
30 #define VTY_MAXHIST 20
31
32 #if defined(VTY_DEPRECATE_INDEX) && defined(__GNUC__) && \
33 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
34 #define INDEX_WARNING __attribute__((deprecated))
35 #else
36 #define INDEX_WARNING
37 #endif
38
39 /* VTY struct. */
40 struct vty
41 {
42 /* File descripter of this vty. */
43 int fd;
44
45 /* output FD, to support stdin/stdout combination */
46 int wfd;
47
48 /* Is this vty connect to file or not */
49 enum {VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV} type;
50
51 /* Node status of this vty */
52 int node;
53
54 /* Failure count */
55 int fail;
56
57 /* Output buffer. */
58 struct buffer *obuf;
59
60 /* Command input buffer */
61 char *buf;
62
63 /* Command input error buffer */
64 char *error_buf;
65
66 /* Command cursor point */
67 int cp;
68
69 /* Command length */
70 int length;
71
72 /* Command max length. */
73 int max;
74
75 /* Histry of command */
76 char *hist[VTY_MAXHIST];
77
78 /* History lookup current point */
79 int hp;
80
81 /* History insert end point */
82 int hindex;
83
84 /* For current referencing point of interface, route-map,
85 access-list etc... */
86 void *index INDEX_WARNING;
87
88 /* qobj object ID (replacement for "index") */
89 uint64_t qobj_index;
90
91 /* qobj second-level object ID (replacement for "index_sub") */
92 uint64_t qobj_index_sub;
93
94 /* For escape character. */
95 unsigned char escape;
96
97 /* Current vty status. */
98 enum {VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE} status;
99
100 /* IAC handling: was the last character received the
101 IAC (interpret-as-command) escape character (and therefore the next
102 character will be the command code)? Refer to Telnet RFC 854. */
103 unsigned char iac;
104
105 /* IAC SB (option subnegotiation) handling */
106 unsigned char iac_sb_in_progress;
107 /* At the moment, we care only about the NAWS (window size) negotiation,
108 and that requires just a 5-character buffer (RFC 1073):
109 <NAWS char> <16-bit width> <16-bit height> */
110 #define TELNET_NAWS_SB_LEN 5
111 unsigned char sb_buf[TELNET_NAWS_SB_LEN];
112 /* How many subnegotiation characters have we received? We just drop
113 those that do not fit in the buffer. */
114 size_t sb_len;
115
116 /* Window width/height. */
117 int width;
118 int height;
119
120 /* Configure lines. */
121 int lines;
122
123 /* Terminal monitor. */
124 int monitor;
125
126 /* In configure mode. */
127 int config;
128
129 /* Read and write thread. */
130 struct thread *t_read;
131 struct thread *t_write;
132
133 /* Timeout seconds and thread. */
134 unsigned long v_timeout;
135 struct thread *t_timeout;
136
137 /* What address is this vty comming from. */
138 char address[SU_ADDRSTRLEN];
139 };
140
141 #undef INDEX_WARNING
142
143 static inline void vty_push_context(struct vty *vty,
144 int node, uint64_t id, void *idx)
145 {
146 vty->node = node;
147 vty->qobj_index = id;
148 #if defined(VTY_DEPRECATE_INDEX) && defined(__GNUC__) && \
149 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
150 #pragma GCC diagnostic push
151 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
152 vty->index = idx;
153 #pragma GCC diagnostic pop
154 #else
155 vty->index = idx;
156 #endif
157 }
158
159 #define VTY_PUSH_CONTEXT(nodeval, ptr) \
160 vty_push_context(vty, nodeval, QOBJ_ID(ptr), NULL)
161 #define VTY_PUSH_CONTEXT_COMPAT(nodeval, ptr) \
162 vty_push_context(vty, nodeval, QOBJ_ID(ptr), ptr)
163 #define VTY_PUSH_CONTEXT_SUB(nodeval, ptr) do { \
164 vty->node = nodeval; \
165 /* qobj_index stays untouched */ \
166 vty->qobj_index_sub = QOBJ_ID(ptr); \
167 } while (0)
168
169 /* can return NULL if context is invalid! */
170 #define VTY_GET_CONTEXT(structname) \
171 QOBJ_GET_TYPESAFE(vty->qobj_index, structname)
172 #define VTY_GET_CONTEXT_SUB(structname) \
173 QOBJ_GET_TYPESAFE(vty->qobj_index_sub, structname)
174
175 /* will return if ptr is NULL. */
176 #define VTY_CHECK_CONTEXT(ptr) \
177 if (!ptr) { \
178 vty_out (vty, "Current configuration object was deleted " \
179 "by another process.%s", VTY_NEWLINE); \
180 return CMD_WARNING; \
181 }
182
183 /* struct structname *ptr = <context>; ptr will never be NULL. */
184 #define VTY_DECLVAR_CONTEXT(structname, ptr) \
185 struct structname *ptr = VTY_GET_CONTEXT(structname); \
186 VTY_CHECK_CONTEXT(ptr);
187 #define VTY_DECLVAR_CONTEXT_SUB(structname, ptr) \
188 struct structname *ptr = VTY_GET_CONTEXT_SUB(structname); \
189 VTY_CHECK_CONTEXT(ptr);
190
191 struct vty_arg
192 {
193 const char *name;
194 const char *value;
195 const char **argv;
196 int argc;
197 };
198
199 /* Integrated configuration file. */
200 #define INTEGRATE_DEFAULT_CONFIG "Quagga.conf"
201
202 /* Small macro to determine newline is newline only or linefeed needed. */
203 #define VTY_NEWLINE ((vty->type == VTY_TERM) ? "\r\n" : "\n")
204
205 /* Default time out value */
206 #define VTY_TIMEOUT_DEFAULT 600
207
208 /* Vty read buffer size. */
209 #define VTY_READ_BUFSIZ 512
210
211 /* Directory separator. */
212 #ifndef DIRECTORY_SEP
213 #define DIRECTORY_SEP '/'
214 #endif /* DIRECTORY_SEP */
215
216 #ifndef IS_DIRECTORY_SEP
217 #define IS_DIRECTORY_SEP(c) ((c) == DIRECTORY_SEP)
218 #endif
219
220 /* GCC have printf type attribute check. */
221 #ifdef __GNUC__
222 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
223 #else
224 #define PRINTF_ATTRIBUTE(a,b)
225 #endif /* __GNUC__ */
226
227 /* Utility macros to convert VTY argument to unsigned long */
228 #define VTY_GET_ULONG(NAME,V,STR) \
229 do { \
230 char *endptr = NULL; \
231 errno = 0; \
232 (V) = strtoul ((STR), &endptr, 10); \
233 if (*(STR) == '-') \
234 { \
235 vty_out (vty, "%% Invalid %s value (dash)%s", NAME, VTY_NEWLINE); \
236 return CMD_WARNING; \
237 } \
238 if (*endptr != '\0') \
239 { \
240 vty_out (vty, "%% Invalid %s value (%s)%s", NAME, endptr, VTY_NEWLINE); \
241 return CMD_WARNING; \
242 } \
243 if (errno) \
244 { \
245 vty_out (vty, "%% Invalid %s value (error %d)%s", NAME, errno, VTY_NEWLINE); \
246 return CMD_WARNING; \
247 } \
248 } while (0)
249
250 /* Utility macros to convert VTY argument to unsigned long long */
251 #define VTY_GET_ULL(NAME,V,STR) \
252 do { \
253 char *endptr = NULL; \
254 errno = 0; \
255 (V) = strtoull ((STR), &endptr, 10); \
256 if (*(STR) == '-') \
257 { \
258 vty_out (vty, "%% Invalid %s value (dash)%s", NAME, VTY_NEWLINE); \
259 return CMD_WARNING; \
260 } \
261 if (*endptr != '\0') \
262 { \
263 vty_out (vty, "%% Invalid %s value (%s)%s", NAME, endptr, VTY_NEWLINE); \
264 return CMD_WARNING; \
265 } \
266 if (errno) \
267 { \
268 vty_out (vty, "%% Invalid %s value (error %d)%s", NAME, errno, VTY_NEWLINE); \
269 return CMD_WARNING; \
270 } \
271 } while (0)
272
273 /*
274 * The logic below ((TMPL) <= ((MIN) && (TMPL) != (MIN)) is
275 * done to circumvent the compiler complaining about
276 * comparing unsigned numbers against zero, if MIN is zero.
277 * NB: The compiler isn't smart enough to supress the warning
278 * if you write (MIN) != 0 && tmpl < (MIN).
279 */
280 #define VTY_GET_INTEGER_RANGE_HEART(NAME,TMPL,STR,MIN,MAX) \
281 do { \
282 VTY_GET_ULONG(NAME, (TMPL), STR); \
283 if ( ((TMPL) <= (MIN) && (TMPL) != (MIN)) || (TMPL) > (MAX) ) \
284 { \
285 vty_out (vty, "%% Invalid %s value%s", NAME, VTY_NEWLINE);\
286 return CMD_WARNING; \
287 } \
288 } while (0)
289
290 #define VTY_GET_INTEGER_RANGE(NAME,V,STR,MIN,MAX) \
291 do { \
292 unsigned long long tmpl; \
293 VTY_GET_INTEGER_RANGE_HEART(NAME,tmpl,STR,MIN,MAX); \
294 (V) = tmpl; \
295 } while (0)
296
297 #define VTY_CHECK_INTEGER_RANGE(NAME,STR,MIN,MAX) \
298 do { \
299 unsigned long tmpl; \
300 VTY_GET_INTEGER_RANGE_HEART(NAME,tmpl,STR,MIN,MAX); \
301 } while (0)
302
303 #define VTY_GET_INTEGER(NAME,V,STR) \
304 VTY_GET_INTEGER_RANGE(NAME,V,STR,0U,UINT32_MAX)
305
306 #define VTY_GET_IPV4_ADDRESS(NAME,V,STR) \
307 do { \
308 int retv; \
309 retv = inet_aton ((STR), &(V)); \
310 if (!retv) \
311 { \
312 vty_out (vty, "%% Invalid %s value%s", NAME, VTY_NEWLINE); \
313 return CMD_WARNING; \
314 } \
315 } while (0)
316
317 #define VTY_GET_IPV4_PREFIX(NAME,V,STR) \
318 do { \
319 int retv; \
320 retv = str2prefix_ipv4 ((STR), &(V)); \
321 if (retv <= 0) \
322 { \
323 vty_out (vty, "%% Invalid %s value%s", NAME, VTY_NEWLINE); \
324 return CMD_WARNING; \
325 } \
326 } while (0)
327
328 #define VTY_WARN_EXPERIMENTAL() \
329 do { \
330 vty_out (vty, "%% WARNING: this command is experimental. Both its name and" \
331 " parameters may%s%% change in a future version of Quagga," \
332 " possibly breaking your configuration!%s", \
333 VTY_NEWLINE, VTY_NEWLINE); \
334 } while (0)
335
336 /* Exported variables */
337 extern char integrate_default[];
338
339 /* Prototypes. */
340 extern void vty_init (struct thread_master *);
341 extern void vty_init_vtysh (void);
342 extern void vty_terminate (void);
343 extern void vty_reset (void);
344 extern struct vty *vty_new (void);
345 extern struct vty *vty_stdio (void (*atclose)(void));
346 extern int vty_out (struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
347 extern void vty_read_config (char *, char *);
348 extern void vty_time_print (struct vty *, int);
349 extern void vty_serv_sock (const char *, unsigned short, const char *);
350 extern void vty_close (struct vty *);
351 extern char *vty_get_cwd (void);
352 extern void vty_log (const char *level, const char *proto,
353 const char *fmt, struct timestamp_control *, va_list);
354 extern int vty_config_lock (struct vty *);
355 extern int vty_config_unlock (struct vty *);
356 extern void vty_config_lockless (void);
357 extern int vty_shell (struct vty *);
358 extern int vty_shell_serv (struct vty *);
359 extern void vty_hello (struct vty *);
360
361 /* Send a fixed-size message to all vty terminal monitors; this should be
362 an async-signal-safe function. */
363 extern void vty_log_fixed (char *buf, size_t len);
364
365 extern const char *vty_get_arg_value (struct vty_arg **, const char *);
366 extern struct vty_arg *vty_get_arg (struct vty_arg **, const char *);
367
368 #endif /* _ZEBRA_VTY_H */