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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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
32 * vntsd consists of multiple components as the follows:
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
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
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.
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.
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.
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.
75 * This is a supporting module for handling special daemon and telnet commands.
78 * supporting modules shared by threads modules.
81 * This is a moudle supporting queue operations. Vntsd organizes its data
82 * in multiple queues <see data structure below>.
85 * This is a manifest to support SMF interfaces.
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.
93 * +----------+ +----------+ +----------+
94 * | group |-->| group |-->| group |-->....
95 * +----------+ +----------+ +----------+
97 * |<-----------------------------------------+
98 * |<------------------------+ |
101 * | +----------+ +----------+ +----------+
102 * +----->| console |---->| console |---->| lconsole |---> ....
103 * +----------+ +----------+ +----------+
105 * | | +----------+ +----------+
106 * | +---->| client |----->| client |----->......
107 * | +----------+ +----------+
110 * |<------------------------------+
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
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
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.
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.
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.
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.
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.
177 #include <sys/wait.h>
178 #include <sys/stat.h>
182 #include <sys/param.h>
183 #include "../../uts/sun4v/sys/vcc.h"
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
193 /* secons before re-send signal for cv_wait */
194 #define VNTSD_CV_WAIT_DELTIME 10
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"
201 /* common messages */
202 #define VNTSD_NO_WRITE_ACCESS_MSG "You do not have write access"
205 #define VNTSD_OPT_DAEMON_OFF 0x1
206 #define VNTSD_OPT_AUTH_CHECK 0x2 /* Enable auth checking */
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.
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.
224 #define VNTSD_GROUP_SIG_WAIT 0x1
225 #define VNTSD_GROUP_CLEAN_CONS 0x2
226 #define VNTSD_GROUP_IN_CLEANUP 0x4
234 * There are two states when a console is removed
236 * the console is being deleted
237 * VNTSD_CONS_SIG_WAIT
238 * console is waiting for all clients to exit.
241 #define VNTSD_CONS_DELETED 0x1 /* deleted */
242 #define VNTSD_CONS_SIG_WAIT 0x2 /* waiting for signal */
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 */
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 */
261 /* client structure */
262 typedef struct vntsd_client
{
263 mutex_t lock
; /* protect the client */
264 uint_t status
; /* client's state */
266 int sockfd
; /* connection socket */
267 thread_t cons_tid
; /* console thread */
269 struct vntsd_cons
*cons
; /* back link to console configuration */
271 char prev_char
; /* previous char read by this client */
275 /* console structure */
276 typedef struct vntsd_cons
{
277 mutex_t lock
; /* protect console port */
278 cond_t cvp
; /* sync between threads */
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 */
285 uint_t cons_no
; /* console port number */
286 char domain_name
[MAXPATHLEN
]; /* domain name */
287 char dev_name
[MAXPATHLEN
];
289 struct vntsd_group
*group
; /* back link to group */
292 /* group structure */
293 typedef struct vntsd_group
{
294 mutex_t lock
; /* protect group */
295 cond_t cvp
; /* sync remove group */
297 uint_t status
; /* group status */
298 char group_name
[MAXPATHLEN
];
299 uint64_t tcp_port
; /* telnet port */
301 thread_t listen_tid
; /* listen thread */
302 int sockfd
; /* listen socket */
304 vntsd_que_t
*conspq
; /* console queue */
305 uint_t num_cons
; /* num console */
307 /* clients have no console connection */
308 vntsd_que_t
*no_cons_clientpq
;
313 /* daemon structure */
314 typedef struct vntsd
{
316 mutex_t lock
; /* protect vntsd */
317 mutex_t tmo_lock
; /* protect tmo queue */
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 */
324 char *devinst
; /* device name */
325 int ctrl_fd
; /* vcc ctrl port */
327 vntsd_que_t
*grouppq
; /* group queue */
328 uint_t num_grps
; /* num groups */
330 vntsd_que_t
*tmoq
; /* timeout queue */
331 thread_t tid
; /* main thread id */
335 /* handle for creating thread */
336 typedef struct vntsd_thr_arg
{
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 */
348 /* vntsd status and error definitions */
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' */
368 /* resource errors */
369 VNTSD_ERR_NO_MEM
, /* memory allocation error */
370 VNTSD_ERR_NO_DRV
, /* cannot open vcc port */
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 */
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 */
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 */
390 /* tcp client read and write errors */
391 VNTSD_ERR_WRITE_CLIENT
, /* writing tcp client err */
393 /* tcp client timeout */
394 VNTSD_ERR_CLIENT_TIMEOUT
, /* client has no activity for timeout */
397 VNTSD_ERR_SIG
, /* unknown signal */
399 /* user input error */
400 VNTSD_ERR_INVALID_INPUT
, /* client typed in */
402 /* internal errors */
403 VNTSD_ERR_EL_NOT_FOUND
, /* element not found */
404 VNTSD_ERR_UNKNOWN_CMD
/* unknown error/cmd */
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 *);
417 /* function prototype */
418 void vntsd_log(vntsd_status_t err
, char *msg
);
419 struct in_addr
vntsd_ip_addr(void);
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
);
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
);
433 boolean_t
vntsd_cons_by_consno(vntsd_cons_t
*consp
, int *cons_id
);
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
);
441 int vntsd_que_insert_after(vntsd_que_t
*que
, void *handle
,
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
);
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
,
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
);
455 int vntsd_set_telnet_options(int fd
);
456 int vntsd_write_client(vntsd_client_t
*client
, char *buffer
,
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
[];
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
);
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
487 #else /* not DEBUG */
494 #endif /* not DEBUG */
500 #endif /* _VNTSD_H */