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