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 /* 210 * group states 211 * When a console is removed or vntsd is exiting, main thread 212 * notifies listen, read and write thread to exit. 213 * After those threads exit, main thread clears up group structurre. 214 * 215 * VNTSD_GROUP_SIG_WAIT 216 * The main thread is waiting for listen thread to exit. 217 * VNTSD_GROUP_CLEAN_CONS 218 * There are console(s) in the group that are being removed. 219 * This is a transition state where the corresponding vcc port has been 220 * removed, but vntsd has not done its clean up yet. 221 * VNTSD_GROUP_IN_CLEANUP 222 * vntsd main thread has started cleaning up the group. 223 */ 224 225 #define VNTSD_GROUP_SIG_WAIT 0x1 226 #define VNTSD_GROUP_CLEAN_CONS 0x2 227 #define VNTSD_GROUP_IN_CLEANUP 0x4 228 229 230 231 232 233 /* 234 * console states 235 * There are two states when a console is removed 236 * VNTSD_CONS_DELETED 237 * the console is being deleted 238 * VNTSD_CONS_SIG_WAIT 239 * console is waiting for all clients to exit. 240 */ 241 242 #define VNTSD_CONS_DELETED 0x1 /* deleted */ 243 #define VNTSD_CONS_SIG_WAIT 0x2 /* waiting for signal */ 244 245 246 #define VNTSD_CLIENT_IO_ERR 0x1 /* reader */ 247 #define VNTSD_CLIENT_DISABLE_DAEMON_CMD 0x2 /* disable daemon cmd */ 248 #define VNTSD_CLIENT_TIMEOUT 0x4 /* timeout */ 249 #define VNTSD_CLIENT_CONS_DELETED 0x8 /* console deleted */ 250 251 /* generic que structure */ 252 typedef struct vntsd_que { 253 void *handle; /* element in queue */ 254 struct vntsd_que *nextp; /* next queue element */ 255 struct vntsd_que *prevp; /* previous queue element */ 256 } vntsd_que_t; 257 258 struct vntsd_cons; 259 struct vntsd_group; 260 struct vntsd; 261 262 /* client structure */ 263 typedef struct vntsd_client { 264 mutex_t lock; /* protect the client */ 265 uint_t status; /* client's state */ 266 267 int sockfd; /* connection socket */ 268 thread_t cons_tid; /* console thread */ 269 270 struct vntsd_cons *cons; /* back link to console configuration */ 271 272 char prev_char; /* previous char read by this client */ 273 274 } vntsd_client_t; 275 276 /* console structure */ 277 typedef struct vntsd_cons { 278 mutex_t lock; /* protect console port */ 279 cond_t cvp; /* sync between threads */ 280 281 vntsd_que_t *clientpq; /* client que */ 282 uint_t status; /* client's state */ 283 int vcc_fd; /* vcc console port */ 284 thread_t wr_tid; /* write thread */ 285 286 uint_t cons_no; /* console port number */ 287 char domain_name[MAXPATHLEN]; /* domain name */ 288 char dev_name[MAXPATHLEN]; 289 290 struct vntsd_group *group; /* back link to group */ 291 } vntsd_cons_t; 292 293 /* group structure */ 294 typedef struct vntsd_group { 295 mutex_t lock; /* protect group */ 296 cond_t cvp; /* sync remove group */ 297 298 uint_t status; /* group status */ 299 char group_name[MAXPATHLEN]; 300 uint64_t tcp_port; /* telnet port */ 301 302 thread_t listen_tid; /* listen thread */ 303 int sockfd; /* listen socket */ 304 305 vntsd_que_t *conspq; /* console queue */ 306 uint_t num_cons; /* num console */ 307 308 /* clients have no console connection */ 309 vntsd_que_t *no_cons_clientpq; 310 struct vntsd *vntsd; 311 312 } vntsd_group_t; 313 314 /* daemon structure */ 315 typedef struct vntsd { 316 317 mutex_t lock; /* protect vntsd */ 318 mutex_t tmo_lock; /* protect tmo queue */ 319 320 int instance; /* vcc instance */ 321 struct in_addr ip_addr; /* ip address to listen */ 322 uint64_t options; /* daemon options */ 323 int timeout; /* connection timeout */ 324 325 char *devinst; /* device name */ 326 int ctrl_fd; /* vcc ctrl port */ 327 328 vntsd_que_t *grouppq; /* group queue */ 329 uint_t num_grps; /* num groups */ 330 331 vntsd_que_t *tmoq; /* timeout queue */ 332 thread_t tid; /* main thread id */ 333 334 } vntsd_t; 335 336 /* handle for creating thread */ 337 typedef struct vntsd_thr_arg { 338 void *handle; 339 void *arg; 340 } vntsd_thr_arg_t; 341 342 /* timeout structure */ 343 typedef struct vntsd_timeout { 344 thread_t tid; /* thread tid */ 345 uint_t minutes; /* idle minutes */ 346 vntsd_client_t *clientp; /* client */ 347 } vntsd_timeout_t; 348 349 /* vntsd status and error definitions */ 350 typedef enum { 351 352 /* status */ 353 VNTSD_SUCCESS = 0, /* success */ 354 VNTSD_STATUS_CONTINUE, /* continue to execute */ 355 VNTSD_STATUS_EXIT_SIG, /* exit siginal */ 356 VNTSD_STATUS_SIG, /* known signal */ 357 VNTSD_STATUS_NO_HOST_NAME, /* no host name set */ 358 VNTSD_STATUS_CLIENT_QUIT, /* client disconnected from group */ 359 VNTSD_STATUS_RESELECT_CONS, /* client re-selecting console */ 360 VNTSD_STATUS_VCC_IO_ERR, /* a vcc io error occurs */ 361 VNTSD_STATUS_MOV_CONS_FORWARD, /* down arrow */ 362 VNTSD_STATUS_MOV_CONS_BACKWARD, /* up arrow */ 363 VNTSD_STATUS_ACQUIRE_WRITER, /* force become the writer */ 364 VNTSD_STATUS_INTR, /* thread receive a signal */ 365 VNTSD_STATUS_DISCONN_CONS, /* disconnect a client from cons */ 366 VNTSD_STATUS_NO_CONS, /* disconnect a client from cons */ 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 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