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 char prev_char; /* previous char read by this client */ 252 253 } vntsd_client_t; 254 255 /* console structure */ 256 typedef struct vntsd_cons { 257 mutex_t lock; /* protect console port */ 258 cond_t cvp; /* sync between threads */ 259 260 vntsd_que_t *clientpq; /* client que */ 261 uint_t status; /* client's state */ 262 int vcc_fd; /* vcc console port */ 263 thread_t wr_tid; /* write thread */ 264 265 uint_t cons_no; /* console port number */ 266 char domain_name[MAXPATHLEN]; /* domain name */ 267 char dev_name[MAXPATHLEN]; 268 269 struct vntsd_group *group; /* back link to group */ 270 } vntsd_cons_t; 271 272 /* group structure */ 273 typedef struct vntsd_group { 274 mutex_t lock; /* protect group */ 275 cond_t cvp; /* sync remove group */ 276 277 uint_t status; /* group status */ 278 char group_name[MAXPATHLEN]; 279 uint64_t tcp_port; /* telnet port */ 280 281 thread_t listen_tid; /* listen thread */ 282 int sockfd; /* listen socket */ 283 284 vntsd_que_t *conspq; /* console queue */ 285 uint_t num_cons; /* num console */ 286 287 /* clients have no console connection */ 288 vntsd_que_t *no_cons_clientpq; 289 struct vntsd *vntsd; 290 291 } vntsd_group_t; 292 293 /* daemon structure */ 294 typedef struct vntsd { 295 296 mutex_t lock; /* protect vntsd */ 297 mutex_t tmo_lock; /* protect tmo queue */ 298 299 int instance; /* vcc instance */ 300 struct in_addr ip_addr; /* ip address to listen */ 301 uint64_t options; /* daemon options */ 302 int timeout; /* connection timeout */ 303 304 char *devinst; /* device name */ 305 int ctrl_fd; /* vcc ctrl port */ 306 307 vntsd_que_t *grouppq; /* group queue */ 308 uint_t num_grps; /* num groups */ 309 310 vntsd_que_t *tmoq; /* timeout queue */ 311 thread_t tid; /* main thread id */ 312 313 } vntsd_t; 314 315 /* handle for creating thread */ 316 typedef struct vntsd_thr_arg { 317 void *handle; 318 void *arg; 319 } vntsd_thr_arg_t; 320 321 /* timeout structure */ 322 typedef struct vntsd_timeout { 323 thread_t tid; /* thread tid */ 324 uint_t minutes; /* idle minutes */ 325 vntsd_client_t *clientp; /* client */ 326 } vntsd_timeout_t; 327 328 /* vntsd status and error definitions */ 329 typedef enum { 330 331 /* status */ 332 VNTSD_SUCCESS = 0, /* success */ 333 VNTSD_STATUS_CONTINUE, /* continue to execute */ 334 VNTSD_STATUS_EXIT_SIG, /* exit siginal */ 335 VNTSD_STATUS_SIG, /* known signal */ 336 VNTSD_STATUS_NO_HOST_NAME, /* no host name set */ 337 VNTSD_STATUS_CLIENT_QUIT, /* client disconnected from group */ 338 VNTSD_STATUS_RESELECT_CONS, /* client re-selecting console */ 339 VNTSD_STATUS_VCC_IO_ERR, /* a vcc io error occurs */ 340 VNTSD_STATUS_MOV_CONS_FORWARD, /* down arrow */ 341 VNTSD_STATUS_MOV_CONS_BACKWARD, /* up arrow */ 342 VNTSD_STATUS_ACQUIRE_WRITER, /* force become the writer */ 343 VNTSD_STATUS_INTR, /* thread receive a signal */ 344 VNTSD_STATUS_DISCONN_CONS, /* disconnect a client from cons */ 345 VNTSD_STATUS_NO_CONS, /* disconnect a client from cons */ 346 347 /* resource errors */ 348 VNTSD_ERR_NO_MEM, /* memory allocation error */ 349 VNTSD_ERR_NO_DRV, /* cannot open vcc port */ 350 351 /* vcc errors */ 352 VNTSD_ERR_VCC_CTRL_DATA, /* vcc ctrl data error */ 353 VNTSD_ERR_VCC_POLL, /* error poll vcc driver */ 354 VNTSD_ERR_VCC_IOCTL, /* vcc ioctl call error */ 355 VNTSD_ERR_VCC_GRP_NAME, /* group name differs from database */ 356 VNTSD_ERR_ADD_CONS_FAILED, /* addition of a console failed */ 357 358 /* create thread errors */ 359 VNTSD_ERR_CREATE_LISTEN_THR, /* listen thread creation failed */ 360 VNTSD_ERR_CREATE_CONS_THR, /* create console thread err */ 361 VNTSD_ERR_CREATE_WR_THR, /* listen thread creation failed */ 362 363 /* listen thread errors */ 364 VNTSD_ERR_LISTEN_SOCKET, /* can not create tcp socket */ 365 VNTSD_ERR_LISTEN_OPTS, /* can not set socket opt */ 366 VNTSD_ERR_LISTEN_BIND, /* can not bind socket */ 367 VNTSD_STATUS_ACCEPT_ERR, /* accept error */ 368 369 /* tcp client read and write errors */ 370 VNTSD_ERR_WRITE_CLIENT, /* writing tcp client err */ 371 372 /* tcp client timeout */ 373 VNTSD_ERR_CLIENT_TIMEOUT, /* client has no activity for timeout */ 374 375 /* signal errors */ 376 VNTSD_ERR_SIG, /* unknown signal */ 377 378 /* user input error */ 379 VNTSD_ERR_INVALID_INPUT, /* client typed in */ 380 381 /* internal errors */ 382 VNTSD_ERR_EL_NOT_FOUND, /* element not found */ 383 VNTSD_ERR_UNKNOWN_CMD /* unknown error/cmd */ 384 385 } vntsd_status_t; 386 387 /* function prototype defines */ 388 typedef int (*compare_func_t)(void *el, void *data); 389 typedef int (*el_func_t)(void *el); 390 typedef void (*clean_func_t)(void *el); 391 typedef void (*sig_handler_t)(int sig); 392 typedef void *(*thr_func_t)(void *); 393 394 395 396 /* function prototype */ 397 void vntsd_log(vntsd_status_t err, char *msg); 398 struct in_addr vntsd_ip_addr(void); 399 400 void vntsd_get_config(vntsd_t *vntsdp); 401 void vntsd_daemon_wakeup(vntsd_t *vntsdp); 402 int vntsd_open_vcc(char *domain_name, uint_t cons_no); 403 void vntsd_delete_cons(vntsd_t *vntsdp); 404 void vntsd_clean_group(vntsd_group_t *groupp); 405 406 407 void *vntsd_listen_thread(vntsd_group_t *groupp); 408 void *vntsd_console_thread(vntsd_thr_arg_t *argp); 409 int vntsd_read(vntsd_client_t *clientp); 410 void *vntsd_write_thread(vntsd_cons_t *consp); 411 412 boolean_t vntsd_cons_by_consno(vntsd_cons_t *consp, int *cons_id); 413 414 int vntsd_que_append(vntsd_que_t **que_hd, void *handle); 415 int vntsd_que_rm(vntsd_que_t **que_hd, void *handle); 416 void *vntsd_que_find(vntsd_que_t *que_hd, compare_func_t 417 compare_func, void *data); 418 void *vntsd_que_walk(vntsd_que_t *que_hd, el_func_t el_func); 419 420 int vntsd_que_insert_after(vntsd_que_t *que, void *handle, 421 void *next); 422 void *vntsd_que_pos(vntsd_que_t *que_hd, void *handle, int pos); 423 void vntsd_free_que(vntsd_que_t **q, clean_func_t clean_func); 424 425 int vntsd_read_char(vntsd_client_t *clientp, char *c); 426 int vntsd_read_line(vntsd_client_t *clientp, char *buf, int *size); 427 int vntsd_read_data(vntsd_client_t *clientp, char *c); 428 int vntsd_get_yes_no(vntsd_client_t *clientp, char *msg, 429 int *yes_no); 430 int vntsd_ctrl_cmd(vntsd_client_t *clientp, char c); 431 int vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c); 432 int vntsd_telnet_cmd(vntsd_client_t *clientp, char c); 433 434 int vntsd_set_telnet_options(int fd); 435 int vntsd_write_client(vntsd_client_t *client, char *buffer, 436 size_t sz); 437 int vntsd_write_fd(int fd, void *buffer, size_t sz); 438 int vntsd_write_line(vntsd_client_t *clientp, char *line); 439 int vntsd_write_lines(vntsd_client_t *clientp, char *lines); 440 extern char vntsd_eol[]; 441 442 void vntsd_clean_group(vntsd_group_t *portp); 443 void vntsd_free_client(vntsd_client_t *clientp); 444 int vntsd_attach_timer(vntsd_timeout_t *tmop); 445 int vntsd_detach_timer(vntsd_timeout_t *tmop); 446 void vntsd_reset_timer(thread_t tid); 447 void vntsd_init_esctable_msgs(void); 448 int vntsd_vcc_ioctl(int ioctl_code, uint_t portno, void *buf); 449 int vntsd_vcc_err(vntsd_cons_t *consp); 450 int vntsd_cons_chk_intr(vntsd_client_t *clientp); 451 boolean_t vntsd_vcc_cons_alive(vntsd_cons_t *consp); 452 boolean_t vntsd_notify_client_cons_del(vntsd_client_t *clientp); 453 int vntsd_chk_group_total_cons(vntsd_group_t *groupp); 454 455 456 #ifdef DEBUG 457 458 extern int vntsddbg; 459 460 #define D1 if (vntsddbg & 0x01) (void) fprintf 461 #define D2 if (vntsddbg & 0x02) (void) fprintf 462 #define D3 if (vntsddbg & 0x04) (void) fprintf 463 #define DERR if (vntsddbg & 0x08) (void) fprintf 464 465 #else /* not DEBUG */ 466 467 #define D1 468 #define D2 469 #define D3 470 #define DERR 471 472 #endif /* not DEBUG */ 473 474 #ifdef __cplusplus 475 } 476 #endif 477 478 #endif /* _VNTSD_H */ 479