xref: /illumos-gate/usr/src/cmd/vntsd/vntsd.h (revision 28b1e50e)
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 2009 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 #ifdef __cplusplus
171 extern "C" {
172 #endif
173 
174 #include	<sys/shm.h>
175 #include	<strings.h>
176 #include	<assert.h>
177 #include	<sys/wait.h>
178 #include	<sys/stat.h>
179 #include	<fcntl.h>
180 #include	<stropts.h>
181 #include	<errno.h>
182 #include	<sys/param.h>
183 #include	"../../uts/sun4v/sys/vcc.h"
184 
185 #define	DEBUG
186 
187 /* vntsd limits */
188 #define	    VNTSD_MAX_BUF_SIZE		128
189 #define	    VNTSD_LINE_LEN		100
190 #define	    VNTSD_MAX_SOCKETS		5
191 #define	    VNTSD_EOL_LEN		2
192 
193 /* secons before re-send signal for cv_wait */
194 #define	    VNTSD_CV_WAIT_DELTIME	10
195 
196 #define	    VCC_PATH_PREFIX     \
197 		"/devices/virtual-devices@100/channel-devices@200/"
198 #define	    VCC_DEVICE_PATH			"/devices%s"
199 #define	    VCC_DEVICE_CTL_PATH VCC_PATH_PREFIX "%s:ctl"
200 
201 /* common messages */
202 #define	    VNTSD_NO_WRITE_ACCESS_MSG	"You do not have write access"
203 
204 /* vntsd options */
205 #define	    VNTSD_OPT_DAEMON_OFF	0x1
206 #define	    VNTSD_OPT_AUTH_CHECK	0x2	/* Enable auth checking */
207 
208 /*
209  * group states
210  * When a console is removed or vntsd is exiting, main thread
211  * notifies listen, read and write thread to exit.
212  * After those threads exit, main thread clears up group structurre.
213  *
214  * VNTSD_GROUP_SIG_WAIT
215  * The main thread is waiting for listen thread to exit.
216  * VNTSD_GROUP_CLEAN_CONS
217  * There are console(s) in the group that are being removed.
218  * This is a transition state where the corresponding vcc port has been
219  * removed, but vntsd has not done its clean up yet.
220  * VNTSD_GROUP_IN_CLEANUP
221  * vntsd main thread has started cleaning up the group.
222  */
223 
224 #define	    VNTSD_GROUP_SIG_WAIT	0x1
225 #define	    VNTSD_GROUP_CLEAN_CONS	0x2
226 #define	    VNTSD_GROUP_IN_CLEANUP	0x4
227 
228 
229 
230 
231 
232 /*
233  * console states
234  * There are two states when a console is removed
235  * VNTSD_CONS_DELETED
236  * the console is being deleted
237  * VNTSD_CONS_SIG_WAIT
238  * console is waiting for all clients to exit.
239  */
240 
241 #define	    VNTSD_CONS_DELETED		0x1	/* deleted */
242 #define	    VNTSD_CONS_SIG_WAIT		0x2	/* waiting for signal */
243 
244 
245 #define	    VNTSD_CLIENT_IO_ERR		    0x1	    /* reader */
246 #define	    VNTSD_CLIENT_DISABLE_DAEMON_CMD 0x2	    /* disable daemon cmd */
247 #define	    VNTSD_CLIENT_TIMEOUT	    0x4	    /* timeout */
248 #define	    VNTSD_CLIENT_CONS_DELETED	    0x8	    /* console deleted */
249 
250 /* generic que structure */
251 typedef	struct vntsd_que {
252 	void			*handle;	/* element in queue */
253 	struct vntsd_que	*nextp;		/* next queue element */
254 	struct vntsd_que	*prevp;		/* previous queue element */
255 } vntsd_que_t;
256 
257 struct vntsd_cons;
258 struct vntsd_group;
259 struct vntsd;
260 
261 /* client structure  */
262 typedef struct vntsd_client {
263 	mutex_t	    lock;	    /* protect the client */
264 	uint_t	    status;	    /* client's state */
265 
266 	int	    sockfd;	    /* connection socket */
267 	thread_t    cons_tid;	    /* console thread */
268 
269 	struct vntsd_cons    *cons; /* back link to console configuration */
270 
271 	char	    prev_char;	    /* previous char read by this client */
272 
273 } vntsd_client_t;
274 
275 /* console structure */
276 typedef struct vntsd_cons {
277 	mutex_t		lock;			    /* protect console port */
278 	cond_t		cvp;			    /* sync between threads */
279 
280 	vntsd_que_t	*clientpq;		    /* client que */
281 	uint_t		status;			    /* client's state */
282 	int		vcc_fd;			    /* vcc console port */
283 	thread_t	wr_tid;			    /* write thread */
284 
285 	uint_t		cons_no;		    /* console port number  */
286 	char		domain_name[MAXPATHLEN];    /* domain name */
287 	char		dev_name[MAXPATHLEN];
288 
289 	struct vntsd_group   *group;		    /* back link to group */
290 } vntsd_cons_t;
291 
292 /* group structure  */
293 typedef struct vntsd_group {
294 	mutex_t	    lock;		    /* protect group */
295 	cond_t	    cvp;		    /* sync remove group */
296 
297 	uint_t	    status;		    /* group status */
298 	char	    group_name[MAXPATHLEN];
299 	uint64_t    tcp_port;		    /* telnet port */
300 
301 	thread_t    listen_tid;		    /* listen thread */
302 	int	    sockfd;		    /* listen socket */
303 
304 	vntsd_que_t *conspq;		    /* console queue */
305 	uint_t	    num_cons;		    /* num console */
306 
307 	/* clients have no console connection */
308 	vntsd_que_t *no_cons_clientpq;
309 	struct vntsd   *vntsd;
310 
311 } vntsd_group_t;
312 
313 /* daemon structure */
314 typedef struct vntsd {
315 
316 	mutex_t		lock;			/* protect vntsd */
317 	mutex_t		tmo_lock;		/* protect tmo queue */
318 
319 	int		instance;		/* vcc instance */
320 	struct in_addr  ip_addr;		/* ip address to listen */
321 	uint64_t	options;		/* daemon options */
322 	int		timeout;		/* connection timeout */
323 
324 	char		*devinst;		/* device name */
325 	int		ctrl_fd;		/* vcc ctrl port */
326 
327 	vntsd_que_t	*grouppq;		/* group queue */
328 	uint_t		num_grps;		/* num groups */
329 
330 	vntsd_que_t	*tmoq;			/* timeout queue */
331 	thread_t	tid;			/* main thread id */
332 
333 } vntsd_t;
334 
335 /* handle for creating thread */
336 typedef	struct vntsd_thr_arg {
337 	void	*handle;
338 	void	*arg;
339 } vntsd_thr_arg_t;
340 
341 /* timeout structure */
342 typedef struct vntsd_timeout {
343 	thread_t	tid;		    /* thread tid */
344 	uint_t		minutes;	    /* idle minutes */
345 	vntsd_client_t	*clientp;	    /* client */
346 } vntsd_timeout_t;
347 
348 /* vntsd status and error  definitions */
349 typedef enum {
350 
351 	/* status */
352 	VNTSD_SUCCESS = 0,		/* success */
353 	VNTSD_STATUS_CONTINUE,		/* continue to execute */
354 	VNTSD_STATUS_EXIT_SIG,		/* exit siginal */
355 	VNTSD_STATUS_SIG,		/* known signal */
356 	VNTSD_STATUS_NO_HOST_NAME,	/* no host name set */
357 	VNTSD_STATUS_CLIENT_QUIT,	/* client disconnected from group */
358 	VNTSD_STATUS_RESELECT_CONS,	/* client re-selecting console */
359 	VNTSD_STATUS_VCC_IO_ERR,	/* a vcc io error occurs */
360 	VNTSD_STATUS_MOV_CONS_FORWARD,	/* down arrow  */
361 	VNTSD_STATUS_MOV_CONS_BACKWARD,	/* up  arrow  */
362 	VNTSD_STATUS_ACQUIRE_WRITER,	/* force become the writer */
363 	VNTSD_STATUS_INTR,		/* thread receive a signal */
364 	VNTSD_STATUS_DISCONN_CONS,	/* disconnect a client from cons */
365 	VNTSD_STATUS_NO_CONS,		/* disconnect a client from cons */
366 	VNTSD_STATUS_AUTH_ENABLED,	/* auth enabled; can't process '-p' */
367 
368 	/* resource errors */
369 	VNTSD_ERR_NO_MEM,		/* memory allocation error */
370 	VNTSD_ERR_NO_DRV,		/* cannot open vcc port */
371 
372 	/* vcc errors */
373 	VNTSD_ERR_VCC_CTRL_DATA,	/* vcc ctrl data error */
374 	VNTSD_ERR_VCC_POLL,		/* error poll vcc driver */
375 	VNTSD_ERR_VCC_IOCTL,		/* vcc ioctl call error */
376 	VNTSD_ERR_VCC_GRP_NAME,		/* group name differs from database */
377 	VNTSD_ERR_ADD_CONS_FAILED,	/* addition of a console failed */
378 
379 	/* create thread errors */
380 	VNTSD_ERR_CREATE_LISTEN_THR,	/* listen thread creation failed */
381 	VNTSD_ERR_CREATE_CONS_THR,	/* create console thread err  */
382 	VNTSD_ERR_CREATE_WR_THR,	/* listen thread creation failed */
383 
384 	/* listen thread errors */
385 	VNTSD_ERR_LISTEN_SOCKET,	/* can not create tcp socket */
386 	VNTSD_ERR_LISTEN_OPTS,		/* can not set socket opt */
387 	VNTSD_ERR_LISTEN_BIND,		/* can not bind socket */
388 	VNTSD_STATUS_ACCEPT_ERR,	/* accept error  */
389 
390 	/* tcp client read and write errors */
391 	VNTSD_ERR_WRITE_CLIENT,		/* writing tcp client err */
392 
393 	/* tcp client timeout */
394 	VNTSD_ERR_CLIENT_TIMEOUT,	/* client has no activity for timeout */
395 
396 	/* signal errors */
397 	VNTSD_ERR_SIG,			/* unknown signal */
398 
399 	/* user input error */
400 	VNTSD_ERR_INVALID_INPUT,	/* client typed in */
401 
402 	/* internal errors */
403 	VNTSD_ERR_EL_NOT_FOUND,		/* element not found */
404 	VNTSD_ERR_UNKNOWN_CMD		/* unknown error/cmd */
405 
406 } vntsd_status_t;
407 
408 /* function prototype defines */
409 typedef	int	    (*compare_func_t)(void *el, void *data);
410 typedef	int	    (*el_func_t)(void *el);
411 typedef	void	    (*clean_func_t)(void *el);
412 typedef	void	    (*sig_handler_t)(int sig);
413 typedef	void	    *(*thr_func_t)(void *);
414 
415 
416 
417 /* function prototype */
418 void		vntsd_log(vntsd_status_t err, char *msg);
419 struct in_addr	vntsd_ip_addr(void);
420 
421 void		vntsd_get_config(vntsd_t *vntsdp);
422 void		vntsd_daemon_wakeup(vntsd_t *vntsdp);
423 int		vntsd_open_vcc(char *domain_name, uint_t cons_no);
424 void		vntsd_delete_cons(vntsd_t *vntsdp);
425 void		vntsd_clean_group(vntsd_group_t *groupp);
426 
427 
428 void		*vntsd_listen_thread(vntsd_group_t *groupp);
429 void		*vntsd_console_thread(vntsd_thr_arg_t *argp);
430 int		vntsd_read(vntsd_client_t *clientp);
431 void		*vntsd_write_thread(vntsd_cons_t *consp);
432 
433 boolean_t	vntsd_cons_by_consno(vntsd_cons_t *consp, int *cons_id);
434 
435 int		vntsd_que_append(vntsd_que_t **que_hd, void *handle);
436 int		vntsd_que_rm(vntsd_que_t **que_hd, void *handle);
437 void		*vntsd_que_find(vntsd_que_t *que_hd, compare_func_t
438 			compare_func, void *data);
439 void		*vntsd_que_walk(vntsd_que_t *que_hd, el_func_t el_func);
440 
441 int		vntsd_que_insert_after(vntsd_que_t *que, void *handle,
442 			void *next);
443 void		*vntsd_que_pos(vntsd_que_t *que_hd, void *handle, int pos);
444 void		vntsd_free_que(vntsd_que_t **q, clean_func_t clean_func);
445 
446 int		vntsd_read_char(vntsd_client_t *clientp, char *c);
447 int		vntsd_read_line(vntsd_client_t *clientp, char *buf, int *size);
448 int		vntsd_read_data(vntsd_client_t *clientp, char *c);
449 int		vntsd_get_yes_no(vntsd_client_t *clientp, char *msg,
450 			int *yes_no);
451 int		vntsd_ctrl_cmd(vntsd_client_t *clientp, char c);
452 int		vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c);
453 int		vntsd_telnet_cmd(vntsd_client_t *clientp, char c);
454 
455 int		vntsd_set_telnet_options(int fd);
456 int		vntsd_write_client(vntsd_client_t *client, char *buffer,
457 	size_t sz);
458 int		vntsd_write_fd(int fd, void *buffer, size_t sz);
459 int		vntsd_write_line(vntsd_client_t *clientp, char *line);
460 int		vntsd_write_lines(vntsd_client_t *clientp, char *lines);
461 extern char	vntsd_eol[];
462 
463 void		vntsd_clean_group(vntsd_group_t *portp);
464 void		vntsd_free_client(vntsd_client_t *clientp);
465 int		vntsd_attach_timer(vntsd_timeout_t *tmop);
466 int		vntsd_detach_timer(vntsd_timeout_t *tmop);
467 void		vntsd_reset_timer(thread_t tid);
468 void		vntsd_init_esctable_msgs(void);
469 int		vntsd_vcc_ioctl(int ioctl_code, uint_t portno, void *buf);
470 int		vntsd_vcc_err(vntsd_cons_t *consp);
471 int		vntsd_cons_chk_intr(vntsd_client_t *clientp);
472 boolean_t	vntsd_vcc_cons_alive(vntsd_cons_t *consp);
473 boolean_t	vntsd_notify_client_cons_del(vntsd_client_t *clientp);
474 int		vntsd_chk_group_total_cons(vntsd_group_t *groupp);
475 boolean_t	vntsd_mark_deleted_cons(vntsd_cons_t *consp);
476 boolean_t	auth_check_fd(int sock_fd, char *group_name);
477 
478 #ifdef	DEBUG
479 
480 extern int vntsddbg;
481 
482 #define	D1 	if (vntsddbg & 0x01) (void) fprintf
483 #define	D2	if (vntsddbg & 0x02) (void) fprintf
484 #define	D3 	if (vntsddbg & 0x04) (void) fprintf
485 #define	DERR 	if (vntsddbg & 0x08) (void) fprintf
486 
487 #else  /* not DEBUG */
488 
489 #define	D1
490 #define	D2
491 #define	D3
492 #define	DERR
493 
494 #endif /* not DEBUG */
495 
496 #ifdef __cplusplus
497 }
498 #endif
499 
500 #endif /* _VNTSD_H */
501