11ae08745Sheppo /* 21ae08745Sheppo * CDDL HEADER START 31ae08745Sheppo * 41ae08745Sheppo * The contents of this file are subject to the terms of the 51ae08745Sheppo * Common Development and Distribution License (the "License"). 61ae08745Sheppo * You may not use this file except in compliance with the License. 71ae08745Sheppo * 81ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 101ae08745Sheppo * See the License for the specific language governing permissions 111ae08745Sheppo * and limitations under the License. 121ae08745Sheppo * 131ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 141ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 161ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 171ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 181ae08745Sheppo * 191ae08745Sheppo * CDDL HEADER END 201ae08745Sheppo */ 211ae08745Sheppo 221ae08745Sheppo /* 231ae08745Sheppo * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 241ae08745Sheppo * Use is subject to license terms. 251ae08745Sheppo */ 261ae08745Sheppo 271ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 281ae08745Sheppo 291ae08745Sheppo /* 301ae08745Sheppo * VNTSD main 311ae08745Sheppo * 321ae08745Sheppo * VNTSD takes the following options: 331ae08745Sheppo * -i <device instance> 341ae08745Sheppo * VCC device instance to use, e.g. virtual-console-concentrator@0. 351ae08745Sheppo * Required option. 361ae08745Sheppo * -p <ip address> 371ae08745Sheppo * IP address VNTSD listens to. 381ae08745Sheppo * -d 391ae08745Sheppo * Do not daemonize. This is only available in a DEBUG build. 401ae08745Sheppo * -t timeout for inactivity 0 = indefinite 411ae08745Sheppo */ 421ae08745Sheppo 431ae08745Sheppo #include <stdio.h> 441ae08745Sheppo #include <sys/types.h> 451ae08745Sheppo #include <stdlib.h> 461ae08745Sheppo #include <string.h> 471ae08745Sheppo #include <unistd.h> 481ae08745Sheppo #include <sys/socket.h> 491ae08745Sheppo #include <arpa/inet.h> 501ae08745Sheppo #include <time.h> 511ae08745Sheppo #include <netinet/in.h> 521ae08745Sheppo #include <thread.h> 531ae08745Sheppo #include <signal.h> 541ae08745Sheppo #include <fcntl.h> 551ae08745Sheppo #include <ctype.h> 561ae08745Sheppo #include <libintl.h> 571ae08745Sheppo #include <locale.h> 581ae08745Sheppo #include <syslog.h> 591ae08745Sheppo #include "vntsd.h" 601ae08745Sheppo #include "chars.h" 611ae08745Sheppo 621ae08745Sheppo #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 631ae08745Sheppo #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't. */ 641ae08745Sheppo #endif 651ae08745Sheppo 661ae08745Sheppo /* global variables */ 671ae08745Sheppo 681ae08745Sheppo #ifdef DEBUG 691ae08745Sheppo int vntsddbg = 0x8; 701ae08745Sheppo #endif 711ae08745Sheppo 721ae08745Sheppo #define MINUTE 60 731ae08745Sheppo 741ae08745Sheppo static vntsd_t *vntsdp; 751ae08745Sheppo 761ae08745Sheppo 771ae08745Sheppo static void vntsd_exit(void); 781ae08745Sheppo /* Signal handler for SIGINT, SIGKILL and SIGHUP */ 791ae08745Sheppo static void 801ae08745Sheppo exit_sig_handler(int sig) 811ae08745Sheppo { 821ae08745Sheppo 831ae08745Sheppo D1(stderr, "t@%d exit_sig_handler%d \n", thr_self(), sig); 841ae08745Sheppo 85*4d39be2bSsg if (thr_self() != vntsdp->tid) { 86*4d39be2bSsg /* not main thread, pass to main thread */ 87*4d39be2bSsg (void) thr_kill(vntsdp->tid, sig); 88*4d39be2bSsg } else { 89*4d39be2bSsg exit(0); 90*4d39be2bSsg } 911ae08745Sheppo } 921ae08745Sheppo 931ae08745Sheppo /* 941ae08745Sheppo * Before a thread reads in client's input, it attaches to vntsd timer so that 951ae08745Sheppo * it can be waken up if a client does not access the connection for 961ae08745Sheppo * VNTSD_INPUT_TIMEOUT(10) minutes. 971ae08745Sheppo */ 981ae08745Sheppo 991ae08745Sheppo /* attach a thread to timer */ 1001ae08745Sheppo int 1011ae08745Sheppo vntsd_attach_timer(vntsd_timeout_t *tmop) 1021ae08745Sheppo { 1031ae08745Sheppo int rv; 1041ae08745Sheppo 1051ae08745Sheppo if (vntsdp->timeout == 0) { 1061ae08745Sheppo return (VNTSD_SUCCESS); 1071ae08745Sheppo } 1081ae08745Sheppo 1091ae08745Sheppo (void) mutex_lock(&vntsdp->tmo_lock); 1101ae08745Sheppo rv = vntsd_que_append(&vntsdp->tmoq, (void *)tmop); 1111ae08745Sheppo (void) mutex_unlock(&vntsdp->tmo_lock); 1121ae08745Sheppo return (rv); 1131ae08745Sheppo } 1141ae08745Sheppo 1151ae08745Sheppo /* detach a thread from timer */ 1161ae08745Sheppo int 1171ae08745Sheppo vntsd_detach_timer(vntsd_timeout_t *tmop) 1181ae08745Sheppo { 1191ae08745Sheppo int rv; 1201ae08745Sheppo 1211ae08745Sheppo if (vntsdp->timeout == 0) { 1221ae08745Sheppo return (VNTSD_SUCCESS); 1231ae08745Sheppo } 1241ae08745Sheppo 1251ae08745Sheppo (void) mutex_lock(&vntsdp->tmo_lock); 1261ae08745Sheppo rv = vntsd_que_rm(&vntsdp->tmoq, (void *)tmop); 1271ae08745Sheppo (void) mutex_unlock(&vntsdp->tmo_lock); 1281ae08745Sheppo 1291ae08745Sheppo return (rv); 1301ae08745Sheppo } 1311ae08745Sheppo 1321ae08745Sheppo /* check threadd's timeout */ 1331ae08745Sheppo static boolean_t 1341ae08745Sheppo chk_timeout(vntsd_timeout_t *tmop) 1351ae08745Sheppo { 1361ae08745Sheppo tmop->minutes++; 1371ae08745Sheppo 1381ae08745Sheppo if (tmop->minutes == vntsdp->timeout) { 1391ae08745Sheppo /* wake up the thread */ 1401ae08745Sheppo tmop->clientp->status |= VNTSD_CLIENT_TIMEOUT; 1411ae08745Sheppo (void) thr_kill(tmop->tid, SIGALRM); 1421ae08745Sheppo } 1431ae08745Sheppo 1441ae08745Sheppo /* return false to walk the queue */ 1451ae08745Sheppo return (B_FALSE); 1461ae08745Sheppo } 1471ae08745Sheppo 1481ae08745Sheppo /* reset timer */ 1491ae08745Sheppo static boolean_t 1501ae08745Sheppo reset_timeout(vntsd_timeout_t *tmop, thread_t tid) 1511ae08745Sheppo { 1521ae08745Sheppo if (tmop->tid == tid) { 1531ae08745Sheppo tmop->minutes = 0; 1541ae08745Sheppo } 1551ae08745Sheppo /* return false to walk the queue */ 1561ae08745Sheppo return (B_FALSE); 1571ae08745Sheppo } 1581ae08745Sheppo 1591ae08745Sheppo void 1601ae08745Sheppo vntsd_reset_timer(thread_t tid) 1611ae08745Sheppo { 1621ae08745Sheppo if (vntsdp->timeout == 0) { 1631ae08745Sheppo return; 1641ae08745Sheppo } 1651ae08745Sheppo 1661ae08745Sheppo (void) mutex_lock(&vntsdp->tmo_lock); 1671ae08745Sheppo (void) vntsd_que_find(vntsdp->tmoq, (compare_func_t)reset_timeout, 1681ae08745Sheppo (void*)tid); 1691ae08745Sheppo (void) mutex_unlock(&vntsdp->tmo_lock); 1701ae08745Sheppo } 1711ae08745Sheppo 1721ae08745Sheppo /* 1731ae08745Sheppo * When alarm goes off, wake up timeout threads. Alarm is set off every 1741ae08745Sheppo * minutes. 1751ae08745Sheppo */ 1761ae08745Sheppo static void 1771ae08745Sheppo vntsd_alarm_sig_handler(int sig) 1781ae08745Sheppo { 1791ae08745Sheppo static thread_t main_thread = 0; 1801ae08745Sheppo 1811ae08745Sheppo D1(stderr, "t@%d alarm signal %d\n", thr_self(), sig); 1821ae08745Sheppo if (vntsdp->timeout == 0) { 1831ae08745Sheppo DERR(stderr, "t@%d alarm signal should not recv %d\n", 1841ae08745Sheppo thr_self(), sig); 1851ae08745Sheppo return; 1861ae08745Sheppo } 1871ae08745Sheppo 1881ae08745Sheppo 1891ae08745Sheppo if (main_thread == 0) { 1901ae08745Sheppo /* initialize thread id */ 1911ae08745Sheppo main_thread = thr_self(); 1921ae08745Sheppo } else if (main_thread != thr_self()) { 1931ae08745Sheppo /* get signal because thread is timeout */ 1941ae08745Sheppo return; 1951ae08745Sheppo } 1961ae08745Sheppo 1971ae08745Sheppo /* in main thread */ 1981ae08745Sheppo (void) mutex_lock(&vntsdp->tmo_lock); 1991ae08745Sheppo 2001ae08745Sheppo /* wake up timeout threads */ 2011ae08745Sheppo (void) vntsd_que_walk(vntsdp->tmoq, (el_func_t)chk_timeout); 2021ae08745Sheppo (void) mutex_unlock(&vntsdp->tmo_lock); 2031ae08745Sheppo 2041ae08745Sheppo /* reset alarm */ 2051ae08745Sheppo (void) alarm(MINUTE); 2061ae08745Sheppo } 2071ae08745Sheppo 2081ae08745Sheppo /* got a SIGUSER1 siginal */ 2091ae08745Sheppo static void 2101ae08745Sheppo vntsd_sig_handler(int sig) 2111ae08745Sheppo { 2121ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 2131ae08745Sheppo 2141ae08745Sheppo (void) snprintf(err_msg, sizeof (err_msg), "sig_handler() sig=%d", 2151ae08745Sheppo sig); 2161ae08745Sheppo 2171ae08745Sheppo if (sig != SIGUSR1) { 2181ae08745Sheppo vntsd_log(VNTSD_STATUS_SIG, err_msg); 2191ae08745Sheppo } 2201ae08745Sheppo } 2211ae08745Sheppo 2221ae08745Sheppo /* vntsd exits */ 2231ae08745Sheppo static void 2241ae08745Sheppo vntsd_exit(void) 2251ae08745Sheppo { 2261ae08745Sheppo D1(stderr, "t@%d vntsd_exit\n", thr_self()); 2271ae08745Sheppo 2281ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 2291ae08745Sheppo 2301ae08745Sheppo if (vntsdp->timeout > 0) { 2311ae08745Sheppo /* cancel the timer */ 2321ae08745Sheppo (void) alarm(0); 2331ae08745Sheppo } 2341ae08745Sheppo /* delete all groups */ 2351ae08745Sheppo vntsd_free_que(&vntsdp->grouppq, (clean_func_t)vntsd_clean_group); 2361ae08745Sheppo 2371ae08745Sheppo /* close control port */ 2381ae08745Sheppo (void) close(vntsdp->ctrl_fd); 2391ae08745Sheppo 2401ae08745Sheppo assert(vntsdp->tmoq == NULL); 2411ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 2421ae08745Sheppo 2431ae08745Sheppo /* clean up vntsdp */ 2441ae08745Sheppo (void) mutex_destroy(&vntsdp->tmo_lock); 2451ae08745Sheppo (void) mutex_destroy(&vntsdp->lock); 2461ae08745Sheppo free(vntsdp); 2471ae08745Sheppo closelog(); 2481ae08745Sheppo } 2491ae08745Sheppo 2501ae08745Sheppo /* 2511ae08745Sheppo * vntsd_help() 2521ae08745Sheppo * print out valid command line options 2531ae08745Sheppo */ 2541ae08745Sheppo static void 2551ae08745Sheppo vntsd_help(void) 2561ae08745Sheppo { 2571ae08745Sheppo 2581ae08745Sheppo (void) fprintf(stderr, gettext("Usage: vntsd -i <VCC device instance> " 2591ae08745Sheppo "[-p <listen address>] [-t <timeout in minutes>]\n")); 2601ae08745Sheppo } 2611ae08745Sheppo 2621ae08745Sheppo 2631ae08745Sheppo #ifdef DEBUG 2641ae08745Sheppo #define DEBUG_OPTIONS "d" 2651ae08745Sheppo #else 2661ae08745Sheppo #define DEBUG_OPTIONS "" 2671ae08745Sheppo #endif 2681ae08745Sheppo 2691ae08745Sheppo int 2701ae08745Sheppo main(int argc, char ** argv) 2711ae08745Sheppo { 2721ae08745Sheppo char *path; 2731ae08745Sheppo struct pollfd poll_drv[1]; 2741ae08745Sheppo struct sigaction act; 2751ae08745Sheppo char *listen_addr = NULL; 2761ae08745Sheppo pid_t pid; 2771ae08745Sheppo int i; 2781ae08745Sheppo int option; 2791ae08745Sheppo int sz; 2801ae08745Sheppo int fd; 2811ae08745Sheppo int n; 2821ae08745Sheppo 2831ae08745Sheppo /* internationalization */ 2841ae08745Sheppo (void) setlocale(LC_MESSAGES, ""); 2851ae08745Sheppo (void) textdomain(TEXT_DOMAIN); 2861ae08745Sheppo vntsd_init_esctable_msgs(); 2871ae08745Sheppo 2881ae08745Sheppo /* initialization */ 2891ae08745Sheppo bzero(&act, sizeof (act)); 2901ae08745Sheppo 2911ae08745Sheppo vntsdp = calloc(sizeof (vntsd_t), 1); 2921ae08745Sheppo if (vntsdp == NULL) { 2931ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "main:vntsdp"); 2941ae08745Sheppo exit(1); 2951ae08745Sheppo } 2961ae08745Sheppo 2971ae08745Sheppo vntsdp->ctrl_fd = -1; 2981ae08745Sheppo vntsdp->devinst = NULL; 2991ae08745Sheppo 3001ae08745Sheppo (void) mutex_init(&vntsdp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 3011ae08745Sheppo (void) mutex_init(&vntsdp->tmo_lock, USYNC_THREAD|LOCK_ERRORCHECK, 3021ae08745Sheppo NULL); 3031ae08745Sheppo 3041ae08745Sheppo /* get CLI options */ 3051ae08745Sheppo while ((option = getopt(argc, argv, "i:t:p:"DEBUG_OPTIONS)) != EOF) { 3061ae08745Sheppo switch (option) { 3071ae08745Sheppo #ifdef DEBUG 3081ae08745Sheppo case 'd': 3091ae08745Sheppo vntsdp->options |= VNTSD_OPT_DAEMON_OFF; 3101ae08745Sheppo break; 3111ae08745Sheppo #endif 3121ae08745Sheppo case 'i': 3131ae08745Sheppo vntsdp->devinst = optarg; 3141ae08745Sheppo break; 3151ae08745Sheppo case 'p': 3161ae08745Sheppo listen_addr = optarg; 3171ae08745Sheppo break; 3181ae08745Sheppo 3191ae08745Sheppo case 't': 3201ae08745Sheppo n = sscanf(optarg, "%d", &(vntsdp->timeout)); 3211ae08745Sheppo if (n != 1) { 3221ae08745Sheppo vntsdp->timeout = -1; 3231ae08745Sheppo } 3241ae08745Sheppo break; 3251ae08745Sheppo 3261ae08745Sheppo default: 3271ae08745Sheppo vntsd_help(); 3281ae08745Sheppo exit(1); 3291ae08745Sheppo } 3301ae08745Sheppo } 3311ae08745Sheppo 3321ae08745Sheppo if ((vntsdp->devinst == NULL) || (vntsdp->timeout == -1)) { 3331ae08745Sheppo vntsd_help(); 3341ae08745Sheppo exit(1); 3351ae08745Sheppo } 3361ae08745Sheppo 3371ae08745Sheppo if (listen_addr == NULL || strcmp(listen_addr, "localhost") == 0) { 3381ae08745Sheppo /* by default listen on loopback interface */ 3391ae08745Sheppo vntsdp->ip_addr.s_addr = htonl(INADDR_LOOPBACK); 3401ae08745Sheppo } else if (strcmp(listen_addr, "any") == 0) { 3411ae08745Sheppo vntsdp->ip_addr.s_addr = htonl(INADDR_ANY); 3421ae08745Sheppo } else { 3431ae08745Sheppo vntsdp->ip_addr.s_addr = inet_addr(listen_addr); 3441ae08745Sheppo if (vntsdp->ip_addr.s_addr == (in_addr_t)(-1)) { 3451ae08745Sheppo (void) fprintf(stderr, 3461ae08745Sheppo gettext("Invalid listen address '%s'\n"), 3471ae08745Sheppo listen_addr); 3481ae08745Sheppo exit(1); 3491ae08745Sheppo } 3501ae08745Sheppo } 3511ae08745Sheppo 3521ae08745Sheppo D3(stderr, "options = %llx, instance = %s, listen = %s\n", 3531ae08745Sheppo vntsdp->options, vntsdp->devinst, 3541ae08745Sheppo listen_addr ? listen_addr : "<null>"); 3551ae08745Sheppo 3561ae08745Sheppo /* open VCC driver control port */ 3571ae08745Sheppo sz = strlen(VCC_DEVICE_CTL_PATH) + strlen(vntsdp->devinst) + 1; 3581ae08745Sheppo path = calloc(sz, 1); 3591ae08745Sheppo if (path == NULL) { 3601ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "main(): alloc dev path"); 3611ae08745Sheppo exit(1); 3621ae08745Sheppo } 3631ae08745Sheppo (void) snprintf(path, sz-1, VCC_DEVICE_CTL_PATH, vntsdp->devinst, 3641ae08745Sheppo sizeof (vntsdp->devinst)); 3651ae08745Sheppo vntsdp->ctrl_fd = open(path, O_RDWR); 3661ae08745Sheppo 3671ae08745Sheppo if (vntsdp->ctrl_fd == -1) { 368*4d39be2bSsg /* print error if device is not present */ 369*4d39be2bSsg syslog(LOG_ERR, 370*4d39be2bSsg "Error opening VCC device control port: %s", 371*4d39be2bSsg path); 372*4d39be2bSsg /* tell SMF no retry */ 373*4d39be2bSsg exit(2); 3741ae08745Sheppo } 375*4d39be2bSsg 376*4d39be2bSsg free(path); 377*4d39be2bSsg 3781ae08745Sheppo if ((vntsdp->options & VNTSD_OPT_DAEMON_OFF) == 0) { 3791ae08745Sheppo /* daemonize it */ 3801ae08745Sheppo pid = fork(); 3811ae08745Sheppo if (pid < 0) { 3821ae08745Sheppo perror("fork"); 3831ae08745Sheppo exit(1); 3841ae08745Sheppo } 3851ae08745Sheppo if (pid > 0) { 3861ae08745Sheppo /* parent */ 3871ae08745Sheppo exit(0); 3881ae08745Sheppo } 3891ae08745Sheppo 3901ae08745Sheppo /* 3911ae08745Sheppo * child process (daemon) 3921ae08745Sheppo * 3931ae08745Sheppo * Close all file descriptors other than 2 and the ctrl fd. 3941ae08745Sheppo */ 3951ae08745Sheppo (void) close(0); 3961ae08745Sheppo (void) close(1); 3971ae08745Sheppo for (i = 3; i < vntsdp->ctrl_fd; i++) { 3981ae08745Sheppo (void) close(i); 3991ae08745Sheppo } 4001ae08745Sheppo closefrom(vntsdp->ctrl_fd + 1); 4011ae08745Sheppo 4021ae08745Sheppo /* obtain a new process group */ 4031ae08745Sheppo (void) setsid(); 4041ae08745Sheppo fd = open("/dev/null", O_RDWR); 4051ae08745Sheppo if (fd < 0) { 4061ae08745Sheppo syslog(LOG_ERR, "Can not open /dev/null"); 4071ae08745Sheppo exit(1); 4081ae08745Sheppo } 4091ae08745Sheppo /* handle standard I/O */ 4101ae08745Sheppo if (dup2(fd, 0) < 0) { 4111ae08745Sheppo syslog(LOG_ERR, "Failed dup2()"); 4121ae08745Sheppo exit(1); 4131ae08745Sheppo } 4141ae08745Sheppo 4151ae08745Sheppo if (dup2(fd, 1) < 0) { 4161ae08745Sheppo syslog(LOG_ERR, "Failed dup2()"); 4171ae08745Sheppo exit(1); 4181ae08745Sheppo } 4191ae08745Sheppo 4201ae08745Sheppo /* ignore terminal signals */ 4211ae08745Sheppo (void) signal(SIGTSTP, SIG_IGN); 4221ae08745Sheppo (void) signal(SIGTTOU, SIG_IGN); 4231ae08745Sheppo (void) signal(SIGTTIN, SIG_IGN); 4241ae08745Sheppo } 4251ae08745Sheppo 4261ae08745Sheppo 4271ae08745Sheppo /* set up signal handlers */ 4281ae08745Sheppo 4291ae08745Sheppo /* exit signals */ 4301ae08745Sheppo act.sa_handler = exit_sig_handler; 4311ae08745Sheppo 4321ae08745Sheppo (void) sigemptyset(&act.sa_mask); 4331ae08745Sheppo (void) sigaction(SIGINT, &act, NULL); 4341ae08745Sheppo (void) sigaction(SIGTERM, &act, NULL); 4351ae08745Sheppo (void) sigaction(SIGHUP, &act, NULL); 4361ae08745Sheppo 4371ae08745Sheppo /* vntsd internal signals */ 4381ae08745Sheppo act.sa_handler = vntsd_sig_handler; 4391ae08745Sheppo (void) sigemptyset(&act.sa_mask); 4401ae08745Sheppo (void) sigaction(SIGUSR1, &act, NULL); 4411ae08745Sheppo 4421ae08745Sheppo 4431ae08745Sheppo act.sa_handler = vntsd_alarm_sig_handler; 4441ae08745Sheppo (void) sigemptyset(&act.sa_mask); 4451ae08745Sheppo (void) sigaction(SIGALRM, &act, NULL); 4461ae08745Sheppo 4471ae08745Sheppo 4481ae08745Sheppo /* setup exit */ 4491ae08745Sheppo (void) atexit(vntsd_exit); 4501ae08745Sheppo 4511ae08745Sheppo 4521ae08745Sheppo 4531ae08745Sheppo /* initialization */ 4541ae08745Sheppo openlog("vntsd", LOG_CONS, LOG_DAEMON); 4551ae08745Sheppo 4561ae08745Sheppo 4571ae08745Sheppo /* set alarm */ 4581ae08745Sheppo if (vntsdp->timeout > 0) { 4591ae08745Sheppo (void) alarm(MINUTE); 4601ae08745Sheppo } 4611ae08745Sheppo 4621ae08745Sheppo vntsdp->tid = thr_self(); 4631ae08745Sheppo 4641ae08745Sheppo /* get exiting consoles from vcc */ 4651ae08745Sheppo vntsd_get_config(vntsdp); 4661ae08745Sheppo 4671ae08745Sheppo for (; ; ) { 4681ae08745Sheppo /* poll vcc for configuration change */ 4691ae08745Sheppo bzero(poll_drv, sizeof (poll_drv)); 4701ae08745Sheppo 4711ae08745Sheppo poll_drv[0].fd = vntsdp->ctrl_fd; 4721ae08745Sheppo poll_drv[0].events = POLLIN; 4731ae08745Sheppo 4741ae08745Sheppo if (poll(poll_drv, 1, -1) == -1) { 4751ae08745Sheppo if (errno == EINTR) { 4761ae08745Sheppo /* wake up because a consle was deleted */ 4771ae08745Sheppo vntsd_delete_cons(vntsdp); 4781ae08745Sheppo continue; 4791ae08745Sheppo } 4801ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_POLL, 4811ae08745Sheppo "vcc control poll err! aborting.."); 4821ae08745Sheppo exit(1); 4831ae08745Sheppo } 4841ae08745Sheppo 4851ae08745Sheppo D1(stderr, "t@%d driver event %x\n", thr_self(), 4861ae08745Sheppo poll_drv[0].revents); 4871ae08745Sheppo 4881ae08745Sheppo vntsd_daemon_wakeup(vntsdp); 489*4d39be2bSsg /* 490*4d39be2bSsg * Main thread may miss a console-delete signal when it is 491*4d39be2bSsg * not polling vcc. check if any console is deleted. 492*4d39be2bSsg */ 493*4d39be2bSsg vntsd_delete_cons(vntsdp); 4941ae08745Sheppo 4951ae08745Sheppo } 4961ae08745Sheppo 4971ae08745Sheppo /*NOTREACHED*/ 4981ae08745Sheppo return (0); 4991ae08745Sheppo } 5001ae08745Sheppo 5011ae08745Sheppo /* export ip_addr */ 5021ae08745Sheppo struct in_addr 5031ae08745Sheppo vntsd_ip_addr(void) 5041ae08745Sheppo { 5051ae08745Sheppo return (vntsdp->ip_addr); 5061ae08745Sheppo } 5071ae08745Sheppo 5081ae08745Sheppo /* 5091ae08745Sheppo * ioctl to vcc control port 5101ae08745Sheppo * Supported ioctls interface are: 5111ae08745Sheppo * ioctl code parameters return data 5121ae08745Sheppo * VCC_NUM_CONSOLE none uint_t no consoles 5131ae08745Sheppo * VCC_CONS_TBL none array of vcc_cons_t 5141ae08745Sheppo * VCC_INQUIRY none vcc_response_t response 5151ae08745Sheppo * VCC_CONS_INFO uint_t portno vcc_cons_t 5161ae08745Sheppo * VCC_CONS_STATUS uint_t portno 5171ae08745Sheppo * VCC_FORCE_CLOSE uint_t portno 5181ae08745Sheppo */ 5191ae08745Sheppo int 5201ae08745Sheppo vntsd_vcc_ioctl(int ioctl_code, uint_t portno, void *buf) 5211ae08745Sheppo { 5221ae08745Sheppo D1(stderr, "t@%d vcc_ioctl@%d code=%x\n", thr_self(), portno, 5231ae08745Sheppo ioctl_code); 5241ae08745Sheppo 5251ae08745Sheppo if ((ioctl_code == (VCC_CONS_INFO)) || 5261ae08745Sheppo (ioctl_code == (VCC_FORCE_CLOSE))) { 5271ae08745Sheppo /* construct vcc in buf */ 5281ae08745Sheppo *((uint_t *)buf) = portno; 5291ae08745Sheppo } 5301ae08745Sheppo 5311ae08745Sheppo if (ioctl(vntsdp->ctrl_fd, ioctl_code, (caddr_t)buf)) { 5327636cb21Slm /* ioctl request error */ 5331ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 5341ae08745Sheppo } 5351ae08745Sheppo 5361ae08745Sheppo return (VNTSD_SUCCESS); 5371ae08745Sheppo } 5381ae08745Sheppo 5391ae08745Sheppo /* 540*4d39be2bSsg * check if a vcc i/o error is caused by removal of a console. If so 541*4d39be2bSsg * wake up main thread to cleanup the console. 5421ae08745Sheppo */ 5431ae08745Sheppo int 5441ae08745Sheppo vntsd_vcc_err(vntsd_cons_t *consp) 5451ae08745Sheppo { 5461ae08745Sheppo vntsd_group_t *groupp; 5471ae08745Sheppo 5481ae08745Sheppo assert(consp); 5491ae08745Sheppo groupp = consp->group; 5501ae08745Sheppo assert(groupp); 5511ae08745Sheppo 5521ae08745Sheppo if (consp->status & VNTSD_CONS_DELETED) { 5531ae08745Sheppo /* console was deleted */ 5541ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 5551ae08745Sheppo } 5561ae08745Sheppo 5571ae08745Sheppo if (vntsd_vcc_cons_alive(consp)) { 5581ae08745Sheppo /* console is ok */ 5591ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 5601ae08745Sheppo } 5611ae08745Sheppo 5621ae08745Sheppo /* console needs to be deleted */ 5631ae08745Sheppo (void) mutex_lock(&consp->lock); 5641ae08745Sheppo consp->status |= VNTSD_CONS_DELETED; 5651ae08745Sheppo 566*4d39be2bSsg /* 567*4d39be2bSsg * main thread will close all clients after receiving console 568*4d39be2bSsg * delete signal. 569*4d39be2bSsg */ 5701ae08745Sheppo (void) mutex_unlock(&consp->lock); 5711ae08745Sheppo 5721ae08745Sheppo /* mark the group */ 5731ae08745Sheppo (void) mutex_lock(&groupp->lock); 5741ae08745Sheppo groupp->status |= VNTSD_GROUP_CLEAN_CONS; 5751ae08745Sheppo (void) mutex_unlock(&groupp->lock); 5761ae08745Sheppo 5771ae08745Sheppo /* signal main thread to deleted console */ 5781ae08745Sheppo (void) thr_kill(vntsdp->tid, SIGUSR1); 5791ae08745Sheppo 5801ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 5811ae08745Sheppo } 582