1N/A/*
1N/A * CDDL HEADER START
1N/A *
1N/A * The contents of this file are subject to the terms of the
1N/A * Common Development and Distribution License (the "License").
1N/A * You may not use this file except in compliance with the License.
1N/A *
1N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1N/A * or http://www.opensolaris.org/os/licensing.
1N/A * See the License for the specific language governing permissions
1N/A * and limitations under the License.
1N/A *
1N/A * When distributing Covered Code, include this CDDL HEADER in each
1N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1N/A * If applicable, add the following below this CDDL HEADER, with the
1N/A * fields enclosed by brackets "[]" replaced with your own identifying
1N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1N/A *
1N/A * CDDL HEADER END
1N/A */
1N/A/*
1N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
1N/A * Use is subject to license terms.
1N/A */
1N/A
1N/A/*
1N/A * vntsd uses configuration information provided by vcc to export access
1N/A * to Ldom console access over regular TCP sockets. When it starts, it opens
1N/A * the vcc driver control port and obtains the list of ports that have been
1N/A * created by the vcc driver as well as TCP port number and group associated
1N/A * with each port.
1N/A * vntsd consists of multiple components as the follows:
1N/A *
1N/A * vntsd.c
1N/A * This module initializes vnts daemon, process user options such as instance
1N/A * number, ip address and etc., and provides main thread to poll any console
1N/A * port change.
1N/A *
1N/A * vntsdvcc.c
1N/A * This module provides vcc driver interface. It opens vcc driver control
1N/A * ports, read initial configuration, and provides interface to read, write and
1N/A * ioctl virtual console ports. This module creates a listen thread for each
1N/A * console group. It further dynamically adds and removes virtual consoles
1N/A * and groups following instructions of the vcc driver. This module
1N/A * is executed in the same thread as vntsd.c which is blocked on vcc control
1N/A * poll interface.
1N/A *
1N/A * listen.c
1N/A * This is a group listen thread. Each group's tcp-port has a listen thread
1N/A * associated with it. The thread is created when a console is associated with
1N/A * a new group and is removed when all consoles in the group are removed.
1N/A *
1N/A * console.c
1N/A * This is a console selection thread. The thread is created when a client
1N/A * connects to a group TCP port and exited when client disconnects. If there is
1N/A * only one console in the group, the client is connected to that console. If
1N/A * there are multiple consoles in the group, the client is asked to select a
1N/A * console. After determining which console to connect to, this thread
1N/A * a write thread if the cient is a writer and it self read in client input.
1N/A *
1N/A * read.c
1N/A * it reads input from a TCP client, processes
1N/A * special daemon and telent commands and write to vcc driver if the client
1N/A * is a writer. The client is a writer if the client is the first one connects
1N/A * to the console. Read thread print out an error message if a reader attempt
1N/A * to input to vcc. Read thread exits if console is deleted, client
1N/A * disconnects, or there is a fatal error.
1N/A *
1N/A * Write.c
1N/A * Write thread is creaed when first client connects to a console. It reads
1N/A * from vcc and writes to all clients that connect to the same console.
1N/A * Write thread exits when all clients disconnect from the console.
1N/A *
1N/A * cmd.c
1N/A * This is a supporting module for handling special daemon and telnet commands.
1N/A *
1N/A * common.c
1N/A * supporting modules shared by threads modules.
1N/A *
1N/A * queue.c
1N/A * This is a moudle supporting queue operations. Vntsd organizes its data
1N/A * in multiple queues <see data structure below>.
1N/A *
1N/A * vntsd.xml
1N/A * This is a manifest to support SMF interfaces.
1N/A *
1N/A * Data structures
1N/A * each group has a vntsd_group_t structure, which contains a queue of
1N/A * all console in that group.
1N/A * each console has a vntsd_cons_t structure, which contains a queue of
1N/A * all clients that connected to the console.
1N/A *
1N/A * +----------+ +----------+ +----------+
1N/A * | group |-->| group |-->| group |-->....
1N/A * +----------+ +----------+ +----------+
1N/A * |
1N/A * |<-----------------------------------------+
1N/A * |<------------------------+ |
1N/A * |<--------+ | |
1N/A * | | | |
1N/A * | +----------+ +----------+ +----------+
1N/A * +----->| console |---->| console |---->| lconsole |---> ....
1N/A * +----------+ +----------+ +----------+
1N/A * | |
1N/A * | | +----------+ +----------+
1N/A * | +---->| client |----->| client |----->......
1N/A * | +----------+ +----------+
1N/A * | | |
1N/A * |<------------+ |
1N/A * |<------------------------------+
1N/A *
1N/A * Locks
1N/A * Each vntsd has one lock to protect the group queue
1N/A * Each group has one lock to protect the console queue, the queue for
1N/A * clients without a console connection and status.
1N/A * Each console has one lock to protect client queue and status.
1N/A * Each client has one lock to protect the state of the client. The client
1N/A * states are:
1N/A *
1N/A * VCC_CLIENT_READER
1N/A * A client is connected to a console as either a writer or a reader.
1N/A * if this client is the first one connects the console, the client is
1N/A * a writer, otherwise the client is a reader. A writer' write thread
1N/A * reads from vcc and send output to all readers connected to the
1N/A * same console. a reader's write thread is blocked until a reader becomes
1N/A * a writer.
1N/A *
1N/A * When a client selected a console, the client becomes a reader if
1N/A * there is another client connected to the console before the client.
1N/A * A client will be a writer if
1N/A * 1. client is the first one connected to the console or
1N/A * 2. client has entered a ~w daemon command or
1N/A * 3. all clients connected to the console before the client have
1N/A * disconnected from the console.
1N/A *
1N/A * VCC_CLIENT_MOVE_CONS_FORWARD
1N/A * VCC_CLIENT_MOVE_CONS_BACKWOARD
1N/A * A client is disconnecting from one console and move to the next or
1N/A * previous console in the group queue.
1N/A * A client is in one of these state if
1N/A * 1. the client has entered the daemon command and
1N/A * 2. the vntsd is in process of switching the client from one
1N/A * console to another.
1N/A *
1N/A * VCC_CLIENT_DISABLE_DAEMON_CMD
1N/A * vntsd is in processing of a client's daemon command or the client is
1N/A * in selecting console.
1N/A * A client is in this state if
1N/A * 1. the client has not selected a console or
1N/A * 2. the vntsd is processing a client's daemon command.
1N/A *
1N/A * VCC_CLIENT_ACQUIRE_WRITER
1N/A * A reader forces to become a writer via vntsd special command.
1N/A * A client is in this state if
1N/A * 1. the client is a reader and
1N/A * 2. client has entered a daemon command to become a writer.
1N/A *
1N/A * VCC_CLIENT_CONS_DELETED
1N/A * The console that the client is connected to is being deleted and
1N/A * waiting for the client to disconnect.
1N/A * A client is in this state if
1N/A * 1. the console a client is connected to is being removed and
1N/A * 2. the vntsd is in process of disconnecting the client from the console.
1N/A *
1N/A */
1N/A
1N/A#ifndef _VNTSD_H
1N/A#define _VNTSD_H
1N/A
1N/A#ifdef __cplusplus
1N/Aextern "C" {
1N/A#endif
1N/A
1N/A#include <sys/shm.h>
1N/A#include <strings.h>
1N/A#include <assert.h>
1N/A#include <sys/wait.h>
1N/A#include <sys/stat.h>
1N/A#include <fcntl.h>
1N/A#include <stropts.h>
1N/A#include <errno.h>
1N/A#include <sys/param.h>
1N/A#include "../../uts/sun4v/sys/vcc.h"
1N/A
1N/A#define DEBUG
1N/A
1N/A/* vntsd limits */
1N/A#define VNTSD_MAX_BUF_SIZE 128
1N/A#define VNTSD_LINE_LEN 100
1N/A#define VNTSD_MAX_SOCKETS 5
1N/A#define VNTSD_EOL_LEN 2
1N/A
1N/A/* secons before re-send signal for cv_wait */
1N/A#define VNTSD_CV_WAIT_DELTIME 10
1N/A
1N/A#define VCC_PATH_PREFIX \
1N/A "/devices/virtual-devices@100/channel-devices@200/"
1N/A#define VCC_DEVICE_PATH "/devices%s"
1N/A#define VCC_DEVICE_CTL_PATH VCC_PATH_PREFIX "%s:ctl"
1N/A
1N/A/* common messages */
1N/A#define VNTSD_NO_WRITE_ACCESS_MSG "You do not have write access"
1N/A
1N/A/* vntsd options */
1N/A#define VNTSD_OPT_DAEMON_OFF 0x1
1N/A#define VNTSD_OPT_AUTH_CHECK 0x2 /* Enable auth checking */
1N/A
1N/A/*
1N/A * group states
1N/A * When a console is removed or vntsd is exiting, main thread
1N/A * notifies listen, read and write thread to exit.
1N/A * After those threads exit, main thread clears up group structurre.
1N/A *
1N/A * VNTSD_GROUP_SIG_WAIT
1N/A * The main thread is waiting for listen thread to exit.
1N/A * VNTSD_GROUP_CLEAN_CONS
1N/A * There are console(s) in the group that are being removed.
1N/A * This is a transition state where the corresponding vcc port has been
1N/A * removed, but vntsd has not done its clean up yet.
1N/A * VNTSD_GROUP_IN_CLEANUP
1N/A * vntsd main thread has started cleaning up the group.
1N/A */
1N/A
1N/A#define VNTSD_GROUP_SIG_WAIT 0x1
1N/A#define VNTSD_GROUP_CLEAN_CONS 0x2
1N/A#define VNTSD_GROUP_IN_CLEANUP 0x4
1N/A
1N/A
1N/A
1N/A
1N/A
1N/A/*
1N/A * console states
1N/A * There are two states when a console is removed
1N/A * VNTSD_CONS_DELETED
1N/A * the console is being deleted
1N/A * VNTSD_CONS_SIG_WAIT
1N/A * console is waiting for all clients to exit.
1N/A */
1N/A
1N/A#define VNTSD_CONS_DELETED 0x1 /* deleted */
1N/A#define VNTSD_CONS_SIG_WAIT 0x2 /* waiting for signal */
1N/A
1N/A
1N/A#define VNTSD_CLIENT_IO_ERR 0x1 /* reader */
1N/A#define VNTSD_CLIENT_DISABLE_DAEMON_CMD 0x2 /* disable daemon cmd */
1N/A#define VNTSD_CLIENT_TIMEOUT 0x4 /* timeout */
1N/A#define VNTSD_CLIENT_CONS_DELETED 0x8 /* console deleted */
1N/A
1N/A/* generic que structure */
1N/Atypedef struct vntsd_que {
1N/A void *handle; /* element in queue */
1N/A struct vntsd_que *nextp; /* next queue element */
1N/A struct vntsd_que *prevp; /* previous queue element */
1N/A} vntsd_que_t;
1N/A
1N/Astruct vntsd_cons;
1N/Astruct vntsd_group;
1N/Astruct vntsd;
1N/A
1N/A/* client structure */
1N/Atypedef struct vntsd_client {
1N/A mutex_t lock; /* protect the client */
1N/A uint_t status; /* client's state */
1N/A
1N/A int sockfd; /* connection socket */
1N/A 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 */