aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/vty/vty.h
blob: 9cadb7ac64af5030f064756e359304c8fc3667e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#pragma once

#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>

#include <osmocom/core/linuxlist.h>
#include <osmocom/core/defs.h>

/*! \defgroup vty VTY (Virtual TTY) interface
 *  @{
 * \file vty.h */

/* GCC have printf type attribute check.  */
#ifdef __GNUC__
#define VTY_PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
#else
#define VTY_PRINTF_ATTRIBUTE(a,b)
#endif				/* __GNUC__ */

/* Does the I/O error indicate that the operation should be retried later? */
#define ERRNO_IO_RETRY(EN) \
	(((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))

/* Vty read buffer size. */
#define VTY_READ_BUFSIZ 512

#define VTY_BUFSIZ 512
#define VTY_MAXHIST 20

/* Number of application / library specific VTY attributes */
#define VTY_CMD_USR_ATTR_NUM 32

/*! VTY events */
enum event {
	VTY_SERV,
	VTY_READ,
	VTY_WRITE,
	VTY_CLOSED,
	VTY_TIMEOUT_RESET,
#ifdef VTYSH
	VTYSH_SERV,
	VTYSH_READ,
	VTYSH_WRITE
#endif				/* VTYSH */
};

enum vty_type {
	VTY_TERM,
	VTY_FILE,
	VTY_SHELL,
	VTY_SHELL_SERV
};

struct vty_parent_node {
	struct llist_head entry;

	/*! private data, specified by creator */
	void *priv;

	/*! Node status of this vty */
	int node;

	/*! When reading from a config file, these are the indenting characters expected for children of
	 * this VTY node. */
	char *indent;
};

/*! Internal representation of a single VTY */
struct vty {
	/*! underlying file (if any) */
	FILE *file;

	/*! private data, specified by creator */
	void *priv;

	/*! File descripter of this vty. */
	int fd;

	/*! Is this vty connect to file or not */
	enum vty_type type;

	/*! Node status of this vty */
	int node;

	/*! Failure count */
	int fail;

	/*! Output buffer. */
	struct buffer *obuf;

	/*! Command input buffer */
	char *buf;

	/*! 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;

	/*! For current referencing point of interface, route-map,
	   access-list etc... */
	void *index;

	/*! For multiple level index treatment such as key chain and key. */
	void *index_sub;

	/*! For escape character. */
	unsigned char escape;

	/*! Current vty status. */
	enum { VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE } status;

	/*! IAC handling
	 *
	 * 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
	/*! sub-negotiation buffer */
	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 */
	int width;
	/*! Widnow height */
	int height;

	/*! Configure lines. */
	int lines;

	int monitor;

	/*! In configure mode. */
	int config;

	/*! List of parent nodes, last item is the outermost parent. */
	struct llist_head parent_nodes;

	/*! When reading from a config file, these are the indenting characters expected for children of
	 * the current VTY node. */
	char *indent;
};

/* Small macro to determine newline is newline only or linefeed needed. */
#define VTY_NEWLINE  ((vty->type == VTY_TERM) ? "\r\n" : "\n")

static inline const char *vty_newline(struct vty *vty)
{
	return VTY_NEWLINE;
}

/*! Information an application registers with the VTY */
struct vty_app_info {
	/*! name of the application */
	const char *name;
	/*! version string of the application */
	const char *version;
	/*! copyright string of the application */
	const char *copyright;
	/*! \ref talloc context */
	void *tall_ctx;
	/*! Call-back for taking actions upon exiting a node.
	 * The return value is ignored, and changes to vty->node and vty->index made in this callback are ignored.
	 * Implicit parent node tracking always sets the correct parent node and vty->index after this callback exits,
	 * so this callback can handle only those nodes that should take specific actions upon node exit, or can be left
	 * NULL entirely. */
	int (*go_parent_cb)(struct vty *vty);
	/*! OBSOLETED: Implicit parent node tracking has replaced the use of this callback. This callback is no longer
	 * called, ever, and can be left NULL. */
	int (*is_config_node)(struct vty *vty, int node)
		OSMO_DEPRECATED("Implicit parent node tracking has replaced the use of this callback. This callback is"
				" no longer called, ever, and can be left NULL.");
	/*! Check if the config is consistent before write */
	int (*config_is_consistent)(struct vty *vty);
	/*! Description of the application specific VTY attributes (optional). */
	const char * usr_attr_desc[VTY_CMD_USR_ATTR_NUM];
	/*! Flag letters of the application specific VTY attributes (optional). */
	char usr_attr_letters[VTY_CMD_USR_ATTR_NUM];
};

/* Prototypes. */
void vty_init(struct vty_app_info *app_info);
int vty_read_config_file(const char *file_name, void *priv);
void vty_init_vtysh (void);
void vty_reset (void);
struct vty *vty_new (void);
struct vty *vty_create (int vty_sock, void *priv);
bool vty_is_active(struct vty *vty);
int vty_out (struct vty *, const char *, ...) VTY_PRINTF_ATTRIBUTE(2, 3);
int vty_out_va(struct vty *vty, const char *format, va_list ap);
int vty_out_newline(struct vty *);
int vty_read(struct vty *vty);
//void vty_time_print (struct vty *, int);
void vty_close (struct vty *);
char *vty_get_cwd (void);
void vty_log (const char *level, const char *proto, const char *fmt, va_list);
int vty_config_lock (struct vty *);
int vty_config_unlock (struct vty *);
int vty_shell (struct vty *);
int vty_shell_serv (struct vty *);
void vty_hello (struct vty *);
void *vty_current_index(struct vty *);
int vty_current_node(struct vty *vty);
int vty_go_parent(struct vty *vty);

/* Return IP address passed to the 'line vty'/'bind' command, or "127.0.0.1" */
const char *vty_get_bind_addr(void);
/** Returns configured port passed to the 'line vty'/'bind' command or default_port. */
int vty_get_bind_port(int default_port);

extern void *tall_vty_ctx;

extern struct cmd_element cfg_description_cmd;
extern struct cmd_element cfg_no_description_cmd;


/**
 * signal handling
 */
enum signal_vty {
	S_VTY_EVENT,
};

struct vty_signal_data {
	enum event event;
	int sock;
	struct vty *vty;
};

/*! @} */