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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* vntsd uses configuration information provided by vcc to export access
* to Ldom console access over regular TCP sockets. When it starts, it opens
* the vcc driver control port and obtains the list of ports that have been
* created by the vcc driver as well as TCP port number and group associated
* with each port.
* vntsd consists of multiple components as the follows:
*
* vntsd.c
* This module initializes vnts daemon, process user options such as instance
* number, ip address and etc., and provides main thread to poll any console
* port change.
*
* vntsdvcc.c
* This module provides vcc driver interface. It opens vcc driver control
* ports, read initial configuration, and provides interface to read, write and
* ioctl virtual console ports. This module creates a listen thread for each
* console group. It further dynamically adds and removes virtual consoles
* and groups following instructions of the vcc driver. This module
* is executed in the same thread as vntsd.c which is blocked on vcc control
* poll interface.
*
* listen.c
* This is a group listen thread. Each group's tcp-port has a listen thread
* associated with it. The thread is created when a console is associated with
* a new group and is removed when all consoles in the group are removed.
*
* console.c
* This is a console selection thread. The thread is created when a client
* connects to a group TCP port and exited when client disconnects. If there is
* only one console in the group, the client is connected to that console. If
* there are multiple consoles in the group, the client is asked to select a
* console. After determining which console to connect to, this thread
* a write thread if the cient is a writer and it self read in client input.
*
* read.c
* it reads input from a TCP client, processes
* special daemon and telent commands and write to vcc driver if the client
* is a writer. The client is a writer if the client is the first one connects
* to the console. Read thread print out an error message if a reader attempt
* to input to vcc. Read thread exits if console is deleted, client
* disconnects, or there is a fatal error.
*
* Write.c
* Write thread is creaed when first client connects to a console. It reads
* from vcc and writes to all clients that connect to the same console.
* Write thread exits when all clients disconnect from the console.
*
* cmd.c
* This is a supporting module for handling special daemon and telnet commands.
*
* common.c
* supporting modules shared by threads modules.
*
* queue.c
* This is a moudle supporting queue operations. Vntsd organizes its data
* in multiple queues <see data structure below>.
*
* vntsd.xml
* This is a manifest to support SMF interfaces.
*
* Data structures
* each group has a vntsd_group_t structure, which contains a queue of
* all console in that group.
* each console has a vntsd_cons_t structure, which contains a queue of
* all clients that connected to the console.
*
* +----------+ +----------+ +----------+
* | group |-->| group |-->| group |-->....
* +----------+ +----------+ +----------+
* |
* |<-----------------------------------------+
* |<------------------------+ |
* |<--------+ | |
* | | | |
* | +----------+ +----------+ +----------+
* +----->| console |---->| console |---->| lconsole |---> ....
* +----------+ +----------+ +----------+
* | |
* | | +----------+ +----------+
* | +---->| client |----->| client |----->......
* | +----------+ +----------+
* | | |
* |<------------+ |
* |<------------------------------+
*
* Locks
* Each vntsd has one lock to protect the group queue
* Each group has one lock to protect the console queue, the queue for
* clients without a console connection and status.
* Each console has one lock to protect client queue and status.
* Each client has one lock to protect the state of the client. The client
* states are:
*
* VCC_CLIENT_READER
* A client is connected to a console as either a writer or a reader.
* if this client is the first one connects the console, the client is
* a writer, otherwise the client is a reader. A writer' write thread
* reads from vcc and send output to all readers connected to the
* same console. a reader's write thread is blocked until a reader becomes
* a writer.
*
* When a client selected a console, the client becomes a reader if
* there is another client connected to the console before the client.
* A client will be a writer if
* 1. client is the first one connected to the console or
* 2. client has entered a ~w daemon command or
* 3. all clients connected to the console before the client have
* disconnected from the console.
*
* VCC_CLIENT_MOVE_CONS_FORWARD
* VCC_CLIENT_MOVE_CONS_BACKWOARD
* A client is disconnecting from one console and move to the next or
* previous console in the group queue.
* A client is in one of these state if
* 1. the client has entered the daemon command and
* 2. the vntsd is in process of switching the client from one
* console to another.
*
* VCC_CLIENT_DISABLE_DAEMON_CMD
* vntsd is in processing of a client's daemon command or the client is
* in selecting console.
* A client is in this state if
* 1. the client has not selected a console or
* 2. the vntsd is processing a client's daemon command.
*
* VCC_CLIENT_ACQUIRE_WRITER
* A reader forces to become a writer via vntsd special command.
* A client is in this state if
* 1. the client is a reader and
* 2. client has entered a daemon command to become a writer.
*
* VCC_CLIENT_CONS_DELETED
* The console that the client is connected to is being deleted and
* waiting for the client to disconnect.
* A client is in this state if
* 1. the console a client is connected to is being removed and
* 2. the vntsd is in process of disconnecting the client from the console.
*
*/
#ifndef _VNTSD_H
#define _VNTSD_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/shm.h>
#include <strings.h>
#include <assert.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stropts.h>
#include <errno.h>
#include <sys/param.h>
#include "../../uts/sun4v/sys/vcc.h"
#define DEBUG
/* vntsd limits */
#define VNTSD_MAX_BUF_SIZE 128
#define VNTSD_LINE_LEN 100
#define VNTSD_MAX_SOCKETS 5
#define VNTSD_EOL_LEN 2
/* secons before re-send signal for cv_wait */
#define VNTSD_CV_WAIT_DELTIME 10
#define VCC_PATH_PREFIX \
"/devices/virtual-devices@100/channel-devices@200/"
#define VCC_DEVICE_PATH "/devices%s"
#define VCC_DEVICE_CTL_PATH VCC_PATH_PREFIX "%s:ctl"
/* common messages */
#define VNTSD_NO_WRITE_ACCESS_MSG "You do not have write access"
/* vntsd options */
#define VNTSD_OPT_DAEMON_OFF 0x1
#define VNTSD_OPT_AUTH_CHECK 0x2 /* Enable auth checking */
/*
* group states
* When a console is removed or vntsd is exiting, main thread
* notifies listen, read and write thread to exit.
* After those threads exit, main thread clears up group structurre.
*
* VNTSD_GROUP_SIG_WAIT
* The main thread is waiting for listen thread to exit.
* VNTSD_GROUP_CLEAN_CONS
* There are console(s) in the group that are being removed.
* This is a transition state where the corresponding vcc port has been
* removed, but vntsd has not done its clean up yet.
* VNTSD_GROUP_IN_CLEANUP
* vntsd main thread has started cleaning up the group.
*/
#define VNTSD_GROUP_SIG_WAIT 0x1
#define VNTSD_GROUP_CLEAN_CONS 0x2
#define VNTSD_GROUP_IN_CLEANUP 0x4
/*
* console states
* There are two states when a console is removed
* VNTSD_CONS_DELETED
* the console is being deleted
* VNTSD_CONS_SIG_WAIT
* console is waiting for all clients to exit.
*/
#define VNTSD_CONS_DELETED 0x1 /* deleted */
#define VNTSD_CONS_SIG_WAIT 0x2 /* waiting for signal */
#define VNTSD_CLIENT_IO_ERR 0x1 /* reader */
#define VNTSD_CLIENT_DISABLE_DAEMON_CMD 0x2 /* disable daemon cmd */
#define VNTSD_CLIENT_TIMEOUT 0x4 /* timeout */
#define VNTSD_CLIENT_CONS_DELETED 0x8 /* console deleted */
/* generic que structure */
typedef struct vntsd_que {
void *handle; /* element in queue */
struct vntsd_que *nextp; /* next queue element */
struct vntsd_que *prevp; /* previous queue element */
} vntsd_que_t;
struct vntsd_cons;
struct vntsd_group;
struct vntsd;
/* client structure */
typedef struct vntsd_client {
mutex_t lock; /* protect the client */
uint_t status; /* client's state */
int sockfd; /* connection socket */
thread_t cons_tid; /* console thread */
struct vntsd_cons *cons; /* back link to console configuration */
char prev_char; /* previous char read by this client */
} vntsd_client_t;
/* console structure */
typedef struct vntsd_cons {
mutex_t lock; /* protect console port */
cond_t cvp; /* sync between threads */
vntsd_que_t *clientpq; /* client que */
uint_t status; /* client's state */
int vcc_fd; /* vcc console port */
thread_t wr_tid; /* write thread */
uint_t cons_no; /* console port number */
char domain_name[MAXPATHLEN]; /* domain name */
char dev_name[MAXPATHLEN];
struct vntsd_group *group; /* back link to group */
} vntsd_cons_t;
/* group structure */
typedef struct vntsd_group {
mutex_t lock; /* protect group */
cond_t cvp; /* sync remove group */
uint_t status; /* group status */
char group_name[MAXPATHLEN];
uint64_t tcp_port; /* telnet port */
thread_t listen_tid; /* listen thread */
int sockfd; /* listen socket */
vntsd_que_t *conspq; /* console queue */
uint_t num_cons; /* num console */
/* clients have no console connection */
vntsd_que_t *no_cons_clientpq;
struct vntsd *vntsd;
} vntsd_group_t;
/* daemon structure */
typedef struct vntsd {
mutex_t lock; /* protect vntsd */
mutex_t tmo_lock; /* protect tmo queue */
int instance; /* vcc instance */
struct in_addr ip_addr; /* ip address to listen */
uint64_t options; /* daemon options */
int timeout; /* connection timeout */
char *devinst; /* device name */
int ctrl_fd; /* vcc ctrl port */
vntsd_que_t *grouppq; /* group queue */
uint_t num_grps; /* num groups */
vntsd_que_t *tmoq; /* timeout queue */
thread_t tid; /* main thread id */
} vntsd_t;
/* handle for creating thread */
typedef struct vntsd_thr_arg {
void *handle;
void *arg;
} vntsd_thr_arg_t;
/* timeout structure */
typedef struct vntsd_timeout {
thread_t tid; /* thread tid */
uint_t minutes; /* idle minutes */
vntsd_client_t *clientp; /* client */
} vntsd_timeout_t;
/* vntsd status and error definitions */
typedef enum {
/* status */
VNTSD_SUCCESS = 0, /* success */
VNTSD_STATUS_CONTINUE, /* continue to execute */
VNTSD_STATUS_EXIT_SIG, /* exit siginal */
VNTSD_STATUS_SIG, /* known signal */
VNTSD_STATUS_NO_HOST_NAME, /* no host name set */
VNTSD_STATUS_CLIENT_QUIT, /* client disconnected from group */
VNTSD_STATUS_RESELECT_CONS, /* client re-selecting console */
VNTSD_STATUS_VCC_IO_ERR, /* a vcc io error occurs */
VNTSD_STATUS_MOV_CONS_FORWARD, /* down arrow */
VNTSD_STATUS_MOV_CONS_BACKWARD, /* up arrow */
VNTSD_STATUS_ACQUIRE_WRITER, /* force become the writer */
VNTSD_STATUS_INTR, /* thread receive a signal */
VNTSD_STATUS_DISCONN_CONS, /* disconnect a client from cons */
VNTSD_STATUS_NO_CONS, /* disconnect a client from cons */
VNTSD_STATUS_AUTH_ENABLED, /* auth enabled; can't process '-p' */
/* resource errors */
VNTSD_ERR_NO_MEM, /* memory allocation error */
VNTSD_ERR_NO_DRV, /* cannot open vcc port */
/* vcc errors */
VNTSD_ERR_VCC_CTRL_DATA, /* vcc ctrl data error */
VNTSD_ERR_VCC_POLL, /* error poll vcc driver */
VNTSD_ERR_VCC_IOCTL, /* vcc ioctl call error */
VNTSD_ERR_VCC_GRP_NAME, /* group name differs from database */
VNTSD_ERR_ADD_CONS_FAILED, /* addition of a console failed */
/* create thread errors */
VNTSD_ERR_CREATE_LISTEN_THR, /* listen thread creation failed */
VNTSD_ERR_CREATE_CONS_THR, /* create console thread err */
VNTSD_ERR_CREATE_WR_THR, /* listen thread creation failed */
/* listen thread errors */
VNTSD_ERR_LISTEN_SOCKET, /* can not create tcp socket */
VNTSD_ERR_LISTEN_OPTS, /* can not set socket opt */
VNTSD_ERR_LISTEN_BIND, /* can not bind socket */
VNTSD_STATUS_ACCEPT_ERR, /* accept error */
/* tcp client read and write errors */
VNTSD_ERR_WRITE_CLIENT, /* writing tcp client err */
/* tcp client timeout */
VNTSD_ERR_CLIENT_TIMEOUT, /* client has no activity for timeout */
/* signal errors */
VNTSD_ERR_SIG, /* unknown signal */
/* user input error */
VNTSD_ERR_INVALID_INPUT, /* client typed in */
/* internal errors */
VNTSD_ERR_EL_NOT_FOUND, /* element not found */
VNTSD_ERR_UNKNOWN_CMD /* unknown error/cmd */
} vntsd_status_t;
/* function prototype defines */
typedef int (*compare_func_t)(void *el, void *data);
typedef int (*el_func_t)(void *el);
typedef void (*clean_func_t)(void *el);
typedef void (*sig_handler_t)(int sig);
typedef void *(*thr_func_t)(void *);
/* function prototype */
void vntsd_log(vntsd_status_t err, char *msg);
struct in_addr vntsd_ip_addr(void);
void vntsd_get_config(vntsd_t *vntsdp);
void vntsd_daemon_wakeup(vntsd_t *vntsdp);
int vntsd_open_vcc(char *domain_name, uint_t cons_no);
void vntsd_delete_cons(vntsd_t *vntsdp);
void vntsd_clean_group(vntsd_group_t *groupp);
void *vntsd_listen_thread(vntsd_group_t *groupp);
void *vntsd_console_thread(vntsd_thr_arg_t *argp);
int vntsd_read(vntsd_client_t *clientp);
void *vntsd_write_thread(vntsd_cons_t *consp);
boolean_t vntsd_cons_by_consno(vntsd_cons_t *consp, int *cons_id);
int vntsd_que_append(vntsd_que_t **que_hd, void *handle);
int vntsd_que_rm(vntsd_que_t **que_hd, void *handle);
void *vntsd_que_find(vntsd_que_t *que_hd, compare_func_t
compare_func, void *data);
void *vntsd_que_walk(vntsd_que_t *que_hd, el_func_t el_func);
int vntsd_que_insert_after(vntsd_que_t *que, void *handle,
void *next);
void *vntsd_que_pos(vntsd_que_t *que_hd, void *handle, int pos);
void vntsd_free_que(vntsd_que_t **q, clean_func_t clean_func);
int vntsd_read_char(vntsd_client_t *clientp, char *c);
int vntsd_read_line(vntsd_client_t *clientp, char *buf, int *size);
int vntsd_read_data(vntsd_client_t *clientp, char *c);
int vntsd_get_yes_no(vntsd_client_t *clientp, char *msg,
int *yes_no);
int vntsd_ctrl_cmd(vntsd_client_t *clientp, char c);
int vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c);
int vntsd_telnet_cmd(vntsd_client_t *clientp, char c);
int vntsd_set_telnet_options(int fd);
int vntsd_write_client(vntsd_client_t *client, char *buffer,
size_t sz);
int vntsd_write_fd(int fd, void *buffer, size_t sz);
int vntsd_write_line(vntsd_client_t *clientp, char *line);
int vntsd_write_lines(vntsd_client_t *clientp, char *lines);
extern char vntsd_eol[];
void vntsd_clean_group(vntsd_group_t *portp);
void vntsd_free_client(vntsd_client_t *clientp);
int vntsd_attach_timer(vntsd_timeout_t *tmop);
int vntsd_detach_timer(vntsd_timeout_t *tmop);
void vntsd_reset_timer(thread_t tid);
void vntsd_init_esctable_msgs(void);
int vntsd_vcc_ioctl(int ioctl_code, uint_t portno, void *buf);
int vntsd_vcc_err(vntsd_cons_t *consp);
int vntsd_cons_chk_intr(vntsd_client_t *clientp);
boolean_t vntsd_vcc_cons_alive(vntsd_cons_t *consp);
boolean_t vntsd_notify_client_cons_del(vntsd_client_t *clientp);
int vntsd_chk_group_total_cons(vntsd_group_t *groupp);
boolean_t vntsd_mark_deleted_cons(vntsd_cons_t *consp);
boolean_t auth_check_fd(int sock_fd, char *group_name);
#ifdef DEBUG
extern int vntsddbg;
#define D1 if (vntsddbg & 0x01) (void) fprintf
#define D2 if (vntsddbg & 0x02) (void) fprintf
#define D3 if (vntsddbg & 0x04) (void) fprintf
#define DERR if (vntsddbg & 0x08) (void) fprintf
#else /* not DEBUG */
#define D1
#define D2
#define D3
#define DERR
#endif /* not DEBUG */
#ifdef __cplusplus
}
#endif
#endif /* _VNTSD_H */
|