xref: /illumos-gate/usr/src/cmd/vntsd/vntsd.h (revision 1ae08745)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * vntsd uses configuration information provided by vcc to export access
28  * to Ldom console access over regular TCP sockets. When it starts, it opens
29  * the vcc driver control port and obtains the list of ports that have been
30  * created by the vcc driver as well as TCP port number and group associated
31  * with each port.
32  * vntsd consists of multiple components as the follows:
33  *
34  * vntsd.c
35  * This module initializes vnts daemon, process user options such as instance
36  * number, ip address and etc., and provides main thread to poll any console
37  * port change.
38  *
39  * vntsdvcc.c
40  * This module provides vcc driver interface. It opens vcc driver control
41  * ports, read initial configuration, and provides interface to read, write and
42  * ioctl virtual console ports. This module creates a listen thread for each
43  * console group. It further dynamically adds and removes virtual consoles
44  * and groups following instructions of the vcc driver. This module
45  * is executed in the same thread as vntsd.c which is blocked on vcc control
46  * poll interface.
47  *
48  * listen.c
49  * This is a group listen thread. Each group's tcp-port has a listen thread
50  * associated with it. The thread is created when a console is associated with
51  * a new group and is removed when all consoles in the group are removed.
52  *
53  * console.c
54  * This is a console selection thread. The thread is created when a client
55  * connects to a group TCP port and exited when client disconnects. If there is
56  * only one console in the group, the client is connected to that console. If
57  * there are multiple consoles in the group, the client is asked to select a
58  * console. After determining which console to connect to, this thread
59  * a write thread if the cient is a writer and it self read in client input.
60  *
61  * read.c
62  * it reads input from a TCP client, processes
63  * special daemon and telent commands and write to vcc driver if the client
64  * is a writer. The client is a writer if the client is the first one connects
65  * to the console. Read thread print out an error message if a reader attempt
66  * to input to vcc. Read thread exits if console is deleted, client
67  * disconnects, or there is a fatal error.
68  *
69  * Write.c
70  * Write thread is creaed when first client connects to a console. It reads
71  * from vcc and writes to all clients that connect to the same console.
72  * Write thread exits when all clients disconnect from the console.
73  *
74  * cmd.c
75  * This is a supporting module for handling special daemon and telnet commands.
76  *
77  * common.c
78  * supporting modules shared by threads modules.
79  *
80  * queue.c
81  * This is a moudle supporting queue operations. Vntsd organizes its data
82  * in multiple queues <see data structure below>.
83  *
84  * vntsd.xml
85  * This is a manifest to support SMF interfaces.
86  *
87  * Data structures
88  * each group has a vntsd_group_t structure, which contains a queue of
89  * all console in that group.
90  * each console has a vntsd_cons_t structure, which contains a queue of
91  * all clients that connected to the console.
92  *
93  *     +----------+   +----------+   +----------+
94  *     |  group	  |-->|  group   |-->|   group  |-->....
95  *     +----------+   +----------+   +----------+
96  *          |
97  *          |<-----------------------------------------+
98  *          |<------------------------+                |
99  *          |<--------+               |                |
100  *          |         |               |                |
101  *          |      +----------+     +----------+     +----------+
102  *          +----->| console  |---->| console  |---->| lconsole |---> ....
103  *                 +----------+     +----------+     +----------+
104  *                     |  |
105  *		       |  |     +----------+      +----------+
106  *		       |  +---->|  client  |----->|   client |----->......
107  *		       |	+----------+      +----------+
108  *		       |	     |                 |
109  *		       |<------------+                 |
110  *		       |<------------------------------+
111  *
112  * Locks
113  *  Each vntsd has one lock to protect the group queue
114  *  Each group has one lock to protect the console queue,  the queue for
115  *  clients without a console connection and status.
116  *  Each console has one lock to protect client queue and status.
117  *  Each client has one lock to protect the state of the client. The client
118  *  states are:
119  *
120  *  VCC_CLIENT_READER
121  *	A client is connected to a console as either a writer or a reader.
122  *	if this client is the first one connects the console, the client is
123  *	a writer, otherwise the client is a reader. A writer' write thread
124  *	reads from vcc and send output to all readers connected to the
125  *	same console. a reader's write thread is blocked until a reader becomes
126  *	a writer.
127  *
128  *	When a client selected a console, the client becomes a reader if
129  *	there is another client connected to the console before the client.
130  *	A client will be a writer if
131  *	1. client is the first one connected to the console or
132  *	2. client has entered a ~w daemon command or
133  *	3. all clients connected to the console before the client have
134  *	   disconnected from the console.
135  *
136  *  VCC_CLIENT_MOVE_CONS_FORWARD
137  *  VCC_CLIENT_MOVE_CONS_BACKWOARD
138  *	A client is disconnecting from one console and move to the next or
139  *	previous console in the group queue.
140  *	A client is in one of these state if
141  *	1. the client has entered the daemon command and
142  *	2. the vntsd is in process of switching the client from one
143  *	   console to another.
144  *
145  *  VCC_CLIENT_DISABLE_DAEMON_CMD
146  *	vntsd is in processing of a client's daemon command or the client is
147  *	in selecting console.
148  *	A client is in this state if
149  *	1. the client has not selected a console or
150  *	2. the vntsd is processing a client's daemon command.
151  *
152  *  VCC_CLIENT_ACQUIRE_WRITER
153  *	A reader forces to become a writer via vntsd special command.
154  *	A client is in this state if
155  *	1. the client is a reader and
156  *	2. client has entered a daemon command to become a writer.
157  *
158  *  VCC_CLIENT_CONS_DELETED
159  *	The console that the client is connected to is being deleted and
160  *	waiting for the client to disconnect.
161  *	A client is in this state if
162  *	1. the console a client is connected to is being removed and
163  *	2. the vntsd is in process of disconnecting the client from the console.
164  *
165  */
166 
167 #ifndef _VNTSD_H
168 #define	_VNTSD_H
169 
170 #pragma ident	"%Z%%M%	%I%	%E% SMI"
171 
172 #ifdef __cplusplus
173 extern "C" {
174 #endif
175 
176 #include	<sys/shm.h>
177 #include	<strings.h>
178 #include	<assert.h>
179 #include	<sys/wait.h>
180 #include	<sys/stat.h>
181 #include	<fcntl.h>
182 #include	<stropts.h>
183 #include	<errno.h>
184 #include	<sys/param.h>
185 #include	"../../uts/sun4v/sys/vcc.h"
186 
187 #define	DEBUG
188 
189 /* vntsd limits */
190 #define	    VNTSD_MAX_BUF_SIZE		128
191 #define	    VNTSD_LINE_LEN		100
192 #define	    VNTSD_MAX_SOCKETS		5
193 #define	    VNTSD_EOL_LEN		2
194 
195 /* secons before re-send signal for cv_wait */
196 #define	    VNTSD_CV_WAIT_DELTIME	10
197 
198 #define	    VCC_PATH_PREFIX     \
199 		"/devices/virtual-devices@100/channel-devices@200/"
200 #define	    VCC_DEVICE_PATH			"/devices%s"
201 #define	    VCC_DEVICE_CTL_PATH VCC_PATH_PREFIX "%s:ctl"
202 
203 /* common messages */
204 #define	    VNTSD_NO_WRITE_ACCESS_MSG	"You do not have write access"
205 
206 /* vntsd options */
207 #define	    VNTSD_OPT_DAEMON_OFF	0x1
208 
209 /* group states */
210 
211 #define	    VNTSD_GROUP_SIG_WAIT	0x1	/*  waiting for signal */
212 #define	    VNTSD_GROUP_CLEAN_CONS	0x2	/*  cons needs to be clean */
213 #define	    VNTSD_GROUP_CLEANUP		0x4	/*  waiting for signal */
214 
215 
216 
217 
218 
219 /* console status */
220 
221 #define	    VNTSD_CONS_DELETED		0x1	/* deleted */
222 #define	    VNTSD_CONS_SIG_WAIT		0x2	/* waiting fro signal */
223 
224 
225 #define	    VNTSD_CLIENT_IO_ERR		    0x1	    /* reader */
226 #define	    VNTSD_CLIENT_DISABLE_DAEMON_CMD 0x2	    /* disable daemon cmd */
227 #define	    VNTSD_CLIENT_TIMEOUT	    0x4	    /* timeout */
228 #define	    VNTSD_CLIENT_CONS_DELETED	    0x8	    /* console deleted */
229 
230 /* generic que structure */
231 typedef	struct vntsd_que {
232 	void			*handle;	/* element in queue */
233 	struct vntsd_que	*nextp;		/* next queue element */
234 	struct vntsd_que	*prevp;		/* previous queue element */
235 } vntsd_que_t;
236 
237 struct vntsd_cons;
238 struct vntsd_group;
239 struct vntsd;
240 
241 /* client structure  */
242 typedef struct vntsd_client {
243 	mutex_t	    lock;	    /* protect the client */
244 	uint_t	    status;	    /* client's state */
245 
246 	int	    sockfd;	    /* connection socket */
247 	thread_t    cons_tid;	    /* console thread */
248 
249 	struct vntsd_cons    *cons; /* back link to console configuration */
250 
251 } vntsd_client_t;
252 
253 /* console structure */
254 typedef struct vntsd_cons {
255 	mutex_t		lock;			    /* protect console port */
256 	cond_t		cvp;			    /* sync between threads */
257 
258 	vntsd_que_t	*clientpq;		    /* client que */
259 	uint_t		status;			    /* client's state */
260 	int		vcc_fd;			    /* vcc console port */
261 	thread_t	wr_tid;			    /* write thread */
262 
263 	uint_t		cons_no;		    /* console port number  */
264 	char		domain_name[MAXPATHLEN];    /* domain name */
265 	char		dev_name[MAXPATHLEN];
266 
267 	struct vntsd_group   *group;		    /* back link to group */
268 } vntsd_cons_t;
269 
270 /* group structure  */
271 typedef struct vntsd_group {
272 	mutex_t	    lock;		    /* protect group */
273 	cond_t	    cvp;		    /* sync remove group */
274 
275 	uint_t	    status;		    /* group status */
276 	char	    group_name[MAXPATHLEN];
277 	uint64_t    tcp_port;		    /* telnet port */
278 
279 	thread_t    listen_tid;		    /* listen thread */
280 	int	    sockfd;		    /* listen socket */
281 
282 	vntsd_que_t *conspq;		    /* console queue */
283 	uint_t	    num_cons;		    /* num console */
284 
285 	/* clients have no console connection */
286 	vntsd_que_t *no_cons_clientpq;
287 	struct vntsd   *vntsd;
288 
289 } vntsd_group_t;
290 
291 /* daemon structure */
292 typedef struct vntsd {
293 
294 	mutex_t		lock;			/* protect vntsd */
295 	mutex_t		tmo_lock;		/* protect tmo queue */
296 
297 	int		instance;		/* vcc instance */
298 	struct in_addr  ip_addr;		/* ip address to listen */
299 	uint64_t	options;		/* daemon options */
300 	int		timeout;		/* connection timeout */
301 
302 	char		*devinst;		/* device name */
303 	int		ctrl_fd;		/* vcc ctrl port */
304 
305 	vntsd_que_t	*grouppq;		/* group queue */
306 	uint_t		num_grps;		/* num groups */
307 
308 	vntsd_que_t	*tmoq;			/* timeout queue */
309 	thread_t	tid;			/* main thread id */
310 
311 } vntsd_t;
312 
313 /* handle for creating thread */
314 typedef	struct vntsd_thr_arg {
315 	void	*handle;
316 	void	*arg;
317 } vntsd_thr_arg_t;
318 
319 /* timeout structure */
320 typedef struct vntsd_timeout {
321 	thread_t	tid;		    /* thread tid */
322 	uint_t		minutes;	    /* idle minutes */
323 	vntsd_client_t	*clientp;	    /* client */
324 } vntsd_timeout_t;
325 
326 /* vntsd status and error  definitions */
327 typedef enum {
328 
329 	/* status */
330 	VNTSD_SUCCESS = 0,		/* success */
331 	VNTSD_STATUS_CONTINUE,		/* continue to execute */
332 	VNTSD_STATUS_EXIT_SIG,		/* exit siginal */
333 	VNTSD_STATUS_SIG,		/* known signal */
334 	VNTSD_STATUS_NO_HOST_NAME,	/* no host name set */
335 	VNTSD_STATUS_CLIENT_QUIT,	/* client disconnected from group */
336 	VNTSD_STATUS_RESELECT_CONS,	/* client re-selecting console */
337 	VNTSD_STATUS_VCC_IO_ERR,	/* a vcc io error occurs */
338 	VNTSD_STATUS_MOV_CONS_FORWARD,	/* down arrow  */
339 	VNTSD_STATUS_MOV_CONS_BACKWARD,	/* up  arrow  */
340 	VNTSD_STATUS_ACQUIRE_WRITER,	/* force become the writer */
341 	VNTSD_STATUS_INTR,		/* thread receive a signal */
342 	VNTSD_STATUS_DISCONN_CONS,	/* disconnect a client from cons */
343 	VNTSD_STATUS_NO_CONS,		/* disconnect a client from cons */
344 
345 	/* resource errors */
346 	VNTSD_ERR_NO_MEM,		/* memory allocation error */
347 	VNTSD_ERR_NO_DRV,		/* cannot open vcc port */
348 
349 	/* vcc errors */
350 	VNTSD_ERR_VCC_CTRL_DATA,	/* vcc ctrl data error */
351 	VNTSD_ERR_VCC_POLL,		/* error poll vcc driver */
352 	VNTSD_ERR_VCC_IOCTL,		/* vcc ioctl call error */
353 	VNTSD_ERR_VCC_GRP_NAME,		/* group name differs from database */
354 	VNTSD_ERR_ADD_CONS_FAILED,	/* addition of a console failed */
355 
356 	/* create thread errors */
357 	VNTSD_ERR_CREATE_LISTEN_THR,	/* listen thread creation failed */
358 	VNTSD_ERR_CREATE_CONS_THR,	/* create console thread err  */
359 	VNTSD_ERR_CREATE_WR_THR,	/* listen thread creation failed */
360 
361 	/* listen thread errors */
362 	VNTSD_ERR_LISTEN_SOCKET,	/* can not create tcp socket */
363 	VNTSD_ERR_LISTEN_OPTS,		/* can not set socket opt */
364 	VNTSD_ERR_LISTEN_BIND,		/* can not bind socket */
365 	VNTSD_STATUS_ACCEPT_ERR,	/* accept error  */
366 
367 	/* tcp client read and write errors */
368 	VNTSD_ERR_WRITE_CLIENT,		/* writing tcp client err */
369 
370 	/* tcp client timeout */
371 	VNTSD_ERR_CLIENT_TIMEOUT,	/* client has no activity for timeout */
372 
373 	/* signal errors */
374 	VNTSD_ERR_SIG,			/* unknown signal */
375 
376 	/* user input error */
377 	VNTSD_ERR_INVALID_INPUT,	/* client typed in */
378 
379 	/* internal errors */
380 	VNTSD_ERR_EL_NOT_FOUND,		/* element not found */
381 	VNTSD_ERR_UNKNOWN_CMD		/* unknown error/cmd */
382 
383 } vntsd_status_t;
384 
385 /* function prototype defines */
386 typedef	int	    (*compare_func_t)(void *el, void *data);
387 typedef	int	    (*el_func_t)(void *el);
388 typedef	void	    (*clean_func_t)(void *el);
389 typedef	void	    (*sig_handler_t)(int sig);
390 typedef	void	    *(*thr_func_t)(void *);
391 
392 
393 
394 /* function prototype */
395 void		vntsd_log(vntsd_status_t err, char *msg);
396 struct in_addr	vntsd_ip_addr(void);
397 
398 void		vntsd_get_config(vntsd_t *vntsdp);
399 void		vntsd_daemon_wakeup(vntsd_t *vntsdp);
400 int		vntsd_open_vcc(char *domain_name, uint_t cons_no);
401 void		vntsd_delete_cons(vntsd_t *vntsdp);
402 void		vntsd_clean_group(vntsd_group_t *groupp);
403 
404 
405 void		*vntsd_listen_thread(vntsd_group_t *groupp);
406 void		*vntsd_console_thread(vntsd_thr_arg_t *argp);
407 int		vntsd_read(vntsd_client_t *clientp);
408 void		*vntsd_write_thread(vntsd_cons_t *consp);
409 
410 boolean_t	vntsd_cons_by_consno(vntsd_cons_t *consp, int *cons_id);
411 
412 int		vntsd_que_append(vntsd_que_t **que_hd, void *handle);
413 int		vntsd_que_rm(vntsd_que_t **que_hd, void *handle);
414 void		*vntsd_que_find(vntsd_que_t *que_hd, compare_func_t
415 			compare_func, void *data);
416 void		*vntsd_que_walk(vntsd_que_t *que_hd, el_func_t el_func);
417 
418 int		vntsd_que_insert_after(vntsd_que_t *que, void *handle,
419 			void *next);
420 void		*vntsd_que_pos(vntsd_que_t *que_hd, void *handle, int pos);
421 void		vntsd_free_que(vntsd_que_t **q, clean_func_t clean_func);
422 
423 int		vntsd_read_char(vntsd_client_t *clientp, char *c);
424 int		vntsd_read_line(vntsd_client_t *clientp, char *buf, int *size);
425 int		vntsd_read_data(vntsd_client_t *clientp, char *c);
426 int		vntsd_get_yes_no(vntsd_client_t *clientp, char *msg,
427 			int *yes_no);
428 int		vntsd_ctrl_cmd(vntsd_client_t *clientp, char c);
429 int		vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c);
430 int		vntsd_telnet_cmd(vntsd_client_t *clientp, char c);
431 
432 int		vntsd_set_telnet_options(int fd);
433 int		vntsd_write_client(vntsd_client_t *client, char *buffer,
434 	size_t sz);
435 int		vntsd_write_fd(int fd, void *buffer, size_t sz);
436 int		vntsd_write_line(vntsd_client_t *clientp, char *line);
437 int		vntsd_write_lines(vntsd_client_t *clientp, char *lines);
438 extern char	vntsd_eol[];
439 
440 void		vntsd_clean_group(vntsd_group_t *portp);
441 void		vntsd_free_client(vntsd_client_t *clientp);
442 int		vntsd_attach_timer(vntsd_timeout_t *tmop);
443 int		vntsd_detach_timer(vntsd_timeout_t *tmop);
444 void		vntsd_reset_timer(thread_t tid);
445 void		vntsd_init_esctable_msgs(void);
446 int		vntsd_vcc_ioctl(int ioctl_code, uint_t portno, void *buf);
447 int		vntsd_vcc_err(vntsd_cons_t *consp);
448 int		vntsd_cons_chk_intr(vntsd_client_t *clientp);
449 boolean_t	vntsd_vcc_cons_alive(vntsd_cons_t *consp);
450 boolean_t	vntsd_notify_client_cons_del(vntsd_client_t *clientp);
451 int		vntsd_chk_group_total_cons(vntsd_group_t *groupp);
452 
453 
454 #ifdef	DEBUG
455 
456 extern int vntsddbg;
457 
458 #define	D1 	if (vntsddbg & 0x01) (void) fprintf
459 #define	D2	if (vntsddbg & 0x02) (void) fprintf
460 #define	D3 	if (vntsddbg & 0x04) (void) fprintf
461 #define	DERR 	if (vntsddbg & 0x08) (void) fprintf
462 
463 #else  /* not DEBUG */
464 
465 #define	D1
466 #define	D2
467 #define	D3
468 #define	DERR
469 
470 #endif /* not DEBUG */
471 
472 #ifdef __cplusplus
473 }
474 #endif
475 
476 #endif /* _VNTSD_H */
477