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 /* 22a93081c1SChris Gerhard * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 231ae08745Sheppo * Use is subject to license terms. 241ae08745Sheppo */ 251ae08745Sheppo 261ae08745Sheppo /* 271ae08745Sheppo * Vntsd handles two types of special commands, one is telnet 281ae08745Sheppo * commands and another is vntsd special commands. 291ae08745Sheppo * telnet commands supported are: 301ae08745Sheppo * WILL 311ae08745Sheppo * WONT 321ae08745Sheppo * DO 331ae08745Sheppo * DONT 341ae08745Sheppo * TEL_ECHO 351ae08745Sheppo * SUPRESS 361ae08745Sheppo * LINEMODE 371ae08745Sheppo * BRK 381ae08745Sheppo * AYT 391ae08745Sheppo * HT 40a93081c1SChris Gerhard * NOP 411ae08745Sheppo * 421ae08745Sheppo * Vntsd special commands are: 438e6a2a04Slm66018 * Send break (~#) 44*41c9e69bSZach Kissel * Send alternate break (~^B) 458e6a2a04Slm66018 * Exit (~.) 468e6a2a04Slm66018 * Force write access (~w) 478e6a2a04Slm66018 * Console next (~n) 488e6a2a04Slm66018 * Console previous (~p) 498e6a2a04Slm66018 * Help (~?) 501ae08745Sheppo */ 511ae08745Sheppo 521ae08745Sheppo #include <stdio.h> 531ae08745Sheppo #include <stdlib.h> 541ae08745Sheppo #include <string.h> 551ae08745Sheppo #include <unistd.h> 561ae08745Sheppo #include <sys/types.h> 571ae08745Sheppo #include <sys/socket.h> 581ae08745Sheppo #include <netinet/in.h> 591ae08745Sheppo #include <thread.h> 601ae08745Sheppo #include <ctype.h> 611ae08745Sheppo #include <sys/termio.h> 621ae08745Sheppo #include <libintl.h> 631ae08745Sheppo #include <syslog.h> 641ae08745Sheppo #include "vntsd.h" 651ae08745Sheppo #include "chars.h" 661ae08745Sheppo 671ae08745Sheppo char vntsd_eol[] = { CR, LF, 0}; 681ae08745Sheppo 691ae08745Sheppo typedef int (*e_func_t)(vntsd_client_t *clientp); 701ae08745Sheppo /* structure for daemon special cmd */ 711ae08745Sheppo typedef struct { 721ae08745Sheppo char e_char; /* char to match on */ 731ae08745Sheppo char *e_help; /* help string */ 741ae08745Sheppo e_func_t e_func; /* command */ 751ae08745Sheppo } esctable_t; 761ae08745Sheppo 771ae08745Sheppo /* genbrk() - send a break to vcc driver */ 781ae08745Sheppo static int 791ae08745Sheppo genbrk(vntsd_client_t *clientp) 801ae08745Sheppo { 811ae08745Sheppo 821ae08745Sheppo vntsd_cons_t *consp; 831ae08745Sheppo 841ae08745Sheppo assert(clientp); 851ae08745Sheppo assert(clientp->cons); 861ae08745Sheppo 871ae08745Sheppo consp = clientp->cons; 881ae08745Sheppo D1(stderr, "t@%d genbrk fd=%d sockfd %d\n", thr_self(), 891ae08745Sheppo consp->vcc_fd, clientp->sockfd); 901ae08745Sheppo 911ae08745Sheppo assert(consp->clientpq != NULL); 921ae08745Sheppo if (consp->clientpq->handle != clientp) { 931ae08745Sheppo /* reader */ 941ae08745Sheppo return (vntsd_write_line(clientp, 951ae08745Sheppo gettext(VNTSD_NO_WRITE_ACCESS_MSG))); 961ae08745Sheppo } 971ae08745Sheppo 981ae08745Sheppo /* writer */ 991ae08745Sheppo if (ioctl(consp->vcc_fd, TCSBRK, NULL)) { 1001ae08745Sheppo return (VNTSD_ERR_VCC_IOCTL); 1011ae08745Sheppo } 1021ae08745Sheppo 1031ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 1041ae08745Sheppo } 1051ae08745Sheppo 106*41c9e69bSZach Kissel 107*41c9e69bSZach Kissel /* genaltbrk() - handle the alternate break sequence */ 108*41c9e69bSZach Kissel static int 109*41c9e69bSZach Kissel genaltbrk(vntsd_client_t *clientp) 110*41c9e69bSZach Kissel { 111*41c9e69bSZach Kissel vntsd_cons_t *consp; 112*41c9e69bSZach Kissel char brkseq[2] = { '~', CNTRL('B')}; 113*41c9e69bSZach Kissel 114*41c9e69bSZach Kissel assert(clientp); 115*41c9e69bSZach Kissel assert(clientp->cons); 116*41c9e69bSZach Kissel 117*41c9e69bSZach Kissel consp = clientp->cons; 118*41c9e69bSZach Kissel D1(stderr, "t@%d genaltbrk fd=%d sockfd %d\n", thr_self(), 119*41c9e69bSZach Kissel consp->vcc_fd, clientp->sockfd); 120*41c9e69bSZach Kissel 121*41c9e69bSZach Kissel assert(consp->clientpq != NULL); 122*41c9e69bSZach Kissel if (consp->clientpq->handle != clientp) { 123*41c9e69bSZach Kissel /* reader */ 124*41c9e69bSZach Kissel return (vntsd_write_line(clientp, 125*41c9e69bSZach Kissel gettext(VNTSD_NO_WRITE_ACCESS_MSG))); 126*41c9e69bSZach Kissel } 127*41c9e69bSZach Kissel 128*41c9e69bSZach Kissel /* 129*41c9e69bSZach Kissel * Unlike the genbrk() function we will just forward the break sequence 130*41c9e69bSZach Kissel * on to vcc and subsequently the underlying console driver. This will 131*41c9e69bSZach Kissel * involve sending the characters '~' and CNTRL('B'). 132*41c9e69bSZach Kissel */ 133*41c9e69bSZach Kissel if ((vntsd_write_fd(clientp->cons->vcc_fd, brkseq, sizeof (brkseq))) == 134*41c9e69bSZach Kissel VNTSD_SUCCESS) 135*41c9e69bSZach Kissel return (VNTSD_STATUS_CONTINUE); 136*41c9e69bSZach Kissel else 137*41c9e69bSZach Kissel return (VNTSD_STATUS_VCC_IO_ERR); 138*41c9e69bSZach Kissel } 139*41c9e69bSZach Kissel 1401ae08745Sheppo /* 1411ae08745Sheppo * console_forward() - cycle client to the next console 1421ae08745Sheppo * in the group queue. 1431ae08745Sheppo */ 1441ae08745Sheppo static int 1451e8f6090Sdtse console_forward(vntsd_client_t *clientp) 1461ae08745Sheppo { 1471e8f6090Sdtse /* forward when there are mutiple consoles in the group */ 1481e8f6090Sdtse if (clientp->cons->group->num_cons > 1) 1491ae08745Sheppo return (VNTSD_STATUS_MOV_CONS_FORWARD); 1501e8f6090Sdtse 1511e8f6090Sdtse return (VNTSD_STATUS_CONTINUE); 1521e8f6090Sdtse 1531ae08745Sheppo } 1541ae08745Sheppo 1551ae08745Sheppo /* 1561ae08745Sheppo * console_backward() - cycle client to the previous 1571ae08745Sheppo * console in the group queue. 1581ae08745Sheppo */ 1591ae08745Sheppo static int 1601e8f6090Sdtse console_backward(vntsd_client_t *clientp) 1611ae08745Sheppo { 1621e8f6090Sdtse /* backward when there are mutiple consoles in the group */ 1631e8f6090Sdtse if (clientp->cons->group->num_cons > 1) 1641ae08745Sheppo return (VNTSD_STATUS_MOV_CONS_BACKWARD); 1651e8f6090Sdtse 1661e8f6090Sdtse return (VNTSD_STATUS_CONTINUE); 1671e8f6090Sdtse 1681ae08745Sheppo } 1691ae08745Sheppo 1701ae08745Sheppo /* acquire_write() - acquire write access to a console. */ 1711ae08745Sheppo static int 1721ae08745Sheppo acquire_write(vntsd_client_t *clientp) 1731ae08745Sheppo { 1741ae08745Sheppo int rv; 1751ae08745Sheppo int yes_no = 1; 1761ae08745Sheppo vntsd_cons_t *consp; 1771ae08745Sheppo 1781ae08745Sheppo assert(clientp); 1791ae08745Sheppo consp = clientp->cons; 1801ae08745Sheppo assert(consp); 1811ae08745Sheppo 1821ae08745Sheppo if (consp->clientpq->handle == clientp) { 1831ae08745Sheppo /* client is a writer */ 1841ae08745Sheppo if ((rv = vntsd_write_line(clientp, 1851ae08745Sheppo gettext("You have write permission"))) != 1861ae08745Sheppo VNTSD_SUCCESS) { 1871ae08745Sheppo return (rv); 1881ae08745Sheppo 1891ae08745Sheppo } 1901ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 1911ae08745Sheppo } 1921ae08745Sheppo 1931ae08745Sheppo /* message to client */ 1941ae08745Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN)) 1951ae08745Sheppo != VNTSD_SUCCESS) { 1961ae08745Sheppo return (rv); 1971ae08745Sheppo } 1981ae08745Sheppo 1991ae08745Sheppo /* 2001ae08745Sheppo * TRANSLATION_NOTE 2011ae08745Sheppo * The following string should be formatted to fit on multiple lines 2021ae08745Sheppo * assuming a line width of at most 78 characters. There must be no 2031ae08745Sheppo * trailing newline. 2041ae08745Sheppo */ 2051ae08745Sheppo if ((rv = vntsd_write_lines(clientp, 2061ae08745Sheppo gettext("Warning: another user currently " 2071ae08745Sheppo "has write permission\nto this console and forcibly removing " 2081ae08745Sheppo "him/her will terminate\nany current write action and all work " 2091ae08745Sheppo "will be lost."))) != VNTSD_SUCCESS) { 2101ae08745Sheppo return (rv); 2111ae08745Sheppo } 2121ae08745Sheppo 2131ae08745Sheppo /* get client yes no */ 2141ae08745Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, 2151ae08745Sheppo VNTSD_EOL_LEN)) != VNTSD_SUCCESS) { 2161ae08745Sheppo return (rv); 2171ae08745Sheppo } 2181ae08745Sheppo 2191ae08745Sheppo if ((rv = vntsd_get_yes_no(clientp, 2201ae08745Sheppo gettext("Would you like to continue?"), 2211ae08745Sheppo &yes_no)) != VNTSD_SUCCESS) { 2221ae08745Sheppo return (rv); 2231ae08745Sheppo } 2241ae08745Sheppo 2251ae08745Sheppo if (yes_no == B_FALSE) { 2261ae08745Sheppo /* client change mind no need to acquire write access */ 2271ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 2281ae08745Sheppo } 2291ae08745Sheppo 2301ae08745Sheppo return (VNTSD_STATUS_ACQUIRE_WRITER); 2311ae08745Sheppo } 2321ae08745Sheppo 2331ae08745Sheppo /* client_exit() - disconnect client from the console. */ 2341ae08745Sheppo static int 2351ae08745Sheppo client_exit(void) 2361ae08745Sheppo { 2371ae08745Sheppo return (VNTSD_STATUS_RESELECT_CONS); 2381ae08745Sheppo } 2391ae08745Sheppo 2401ae08745Sheppo static int daemon_cmd_help(vntsd_client_t *clientp); 2411ae08745Sheppo 2421ae08745Sheppo /* table for daemon commands */ 2431ae08745Sheppo 2441ae08745Sheppo static esctable_t etable[] = { 2451ae08745Sheppo 2461ae08745Sheppo /* send a break to vcc */ 2478e6a2a04Slm66018 {'#', "Send break", genbrk}, 2481ae08745Sheppo 249*41c9e69bSZach Kissel /* alternate break sequence */ 250*41c9e69bSZach Kissel {CNTRL('B'), "Send alternate break", genaltbrk}, 251*41c9e69bSZach Kissel 2521ae08745Sheppo /* exit */ 2538e6a2a04Slm66018 {'.', "Exit from this console", (e_func_t)client_exit}, 2541ae08745Sheppo 2551ae08745Sheppo /* acquire write access */ 2568e6a2a04Slm66018 {'w', "Force write access", acquire_write}, 2571ae08745Sheppo 2581ae08745Sheppo /* connect to next console in queue */ 2598e6a2a04Slm66018 {'n', "Console next", (e_func_t)console_forward}, 2601ae08745Sheppo 2611ae08745Sheppo /* connect to previous console in queue */ 2628e6a2a04Slm66018 {'p', "Console previous", (e_func_t)console_backward}, 2631ae08745Sheppo 2641ae08745Sheppo /* help must be next to last */ 2658e6a2a04Slm66018 {'?', "Help", daemon_cmd_help}, 2661ae08745Sheppo 2671ae08745Sheppo /* table terminator */ 2681ae08745Sheppo {0, 0, 0} 2691ae08745Sheppo }; 2701ae08745Sheppo 2711ae08745Sheppo void 2721ae08745Sheppo vntsd_init_esctable_msgs(void) 2731ae08745Sheppo { 2741ae08745Sheppo esctable_t *p; 2751ae08745Sheppo 2761ae08745Sheppo for (p = etable; p->e_char != '\0'; p++) { 2771ae08745Sheppo p->e_help = gettext(p->e_help); 2781ae08745Sheppo } 2791ae08745Sheppo } 2801ae08745Sheppo 2811ae08745Sheppo /* daemon_cmd_help() - print help. */ 2821ae08745Sheppo static int 2831ae08745Sheppo daemon_cmd_help(vntsd_client_t *clientp) 2841ae08745Sheppo { 2851ae08745Sheppo esctable_t *p; 2861ae08745Sheppo int rv; 2871ae08745Sheppo char buf[VNTSD_LINE_LEN]; 2881ae08745Sheppo 2891ae08745Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, 2901ae08745Sheppo VNTSD_EOL_LEN)) != VNTSD_SUCCESS) { 2911ae08745Sheppo return (rv); 2921ae08745Sheppo } 2931ae08745Sheppo 2941ae08745Sheppo /* 2951ae08745Sheppo * TRANSLATION_NOTE 2961ae08745Sheppo * VNTSD is the name of the VNTS daemon and should not be translated. 2971ae08745Sheppo */ 2981ae08745Sheppo if ((rv = vntsd_write_line(clientp, gettext("VNTSD commands"))) != 2991ae08745Sheppo VNTSD_SUCCESS) { 3001ae08745Sheppo return (rv); 3011ae08745Sheppo } 3021ae08745Sheppo 3031ae08745Sheppo for (p = etable; p->e_char; p++) { 304*41c9e69bSZach Kissel 305*41c9e69bSZach Kissel if (p->e_char == CNTRL('B')) { 306*41c9e69bSZach Kissel (void) snprintf(buf, sizeof (buf), "~^B --%s", 307*41c9e69bSZach Kissel p->e_help); 308*41c9e69bSZach Kissel } else { 3091ae08745Sheppo (void) snprintf(buf, sizeof (buf), 3101ae08745Sheppo "~%c --%s", p->e_char, p->e_help); 311*41c9e69bSZach Kissel } 3121ae08745Sheppo 3131ae08745Sheppo if ((rv = vntsd_write_line(clientp, buf)) != VNTSD_SUCCESS) { 3141ae08745Sheppo return (rv); 3151ae08745Sheppo } 3161ae08745Sheppo } 3171ae08745Sheppo 3181ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 3191ae08745Sheppo } 3201ae08745Sheppo 3211ae08745Sheppo /* exit from daemon command */ 3221ae08745Sheppo static int 3231ae08745Sheppo exit_daemon_cmd(vntsd_client_t *clientp, int rv) 3241ae08745Sheppo { 3251ae08745Sheppo (void) mutex_lock(&clientp->lock); 3261ae08745Sheppo clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD; 3271ae08745Sheppo (void) mutex_unlock(&clientp->lock); 3281ae08745Sheppo return (rv); 3291ae08745Sheppo } 3301ae08745Sheppo 331d10e4ef2Snarayan /* 332d10e4ef2Snarayan * vntsd_process_daemon_cmd() - special commands 333d10e4ef2Snarayan * "<RET>~" vntsd daemon commands 334d10e4ef2Snarayan * "<RET>~~" enter '~' character 335d10e4ef2Snarayan */ 3361ae08745Sheppo int 3371ae08745Sheppo vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c) 3381ae08745Sheppo { 3391ae08745Sheppo esctable_t *p; 3401ae08745Sheppo int rv; 341d10e4ef2Snarayan char prev_char; 3421ae08745Sheppo 343d10e4ef2Snarayan prev_char = clientp->prev_char; 344d10e4ef2Snarayan 345d10e4ef2Snarayan if (c != VNTSD_DAEMON_CMD || (prev_char != 0 && prev_char != CR)) { 3461ae08745Sheppo /* not a daemon command */ 3471ae08745Sheppo return (VNTSD_SUCCESS); 3481ae08745Sheppo } 3491ae08745Sheppo 3501ae08745Sheppo if (clientp->status & VNTSD_CLIENT_DISABLE_DAEMON_CMD) { 3511ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 3521ae08745Sheppo } 3531ae08745Sheppo 3541ae08745Sheppo /* no reentry to process_daemon_cmd */ 3551ae08745Sheppo (void) mutex_lock(&clientp->lock); 3561ae08745Sheppo clientp->status |= VNTSD_CLIENT_DISABLE_DAEMON_CMD; 3571ae08745Sheppo (void) mutex_unlock(&clientp->lock); 3581ae08745Sheppo 3591ae08745Sheppo D3(stderr, "t@%d process_daemon_cmd %d %d \n", thr_self(), 3601ae08745Sheppo clientp->cons->vcc_fd, clientp->sockfd); 3611ae08745Sheppo 3621ae08745Sheppo /* read in command */ 3631ae08745Sheppo if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) { 3641ae08745Sheppo return (exit_daemon_cmd(clientp, rv)); 3651ae08745Sheppo } 3661ae08745Sheppo 367d10e4ef2Snarayan if (c == VNTSD_DAEMON_CMD) { 368d10e4ef2Snarayan /* 369d10e4ef2Snarayan * received another '~' 370d10e4ef2Snarayan * a user types '~~' to get '~' 371d10e4ef2Snarayan */ 372d10e4ef2Snarayan (void) mutex_lock(&clientp->lock); 373d10e4ef2Snarayan clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD; 374d10e4ef2Snarayan (void) mutex_unlock(&clientp->lock); 375d10e4ef2Snarayan return (VNTSD_SUCCESS); 376d10e4ef2Snarayan } 377d10e4ef2Snarayan 3781ae08745Sheppo for (p = etable; p->e_char; p++) { 3791ae08745Sheppo if (p->e_char == c) { 3801ae08745Sheppo /* found match */ 3811ae08745Sheppo assert(p->e_func); 3821ae08745Sheppo rv = (*p->e_func)(clientp); 3831ae08745Sheppo return (exit_daemon_cmd(clientp, rv)); 3841ae08745Sheppo } 3851ae08745Sheppo } 3861ae08745Sheppo 3871ae08745Sheppo /* no match, print out the help */ 3881ae08745Sheppo p--; 3891ae08745Sheppo assert(p->e_char == '?'); 3901ae08745Sheppo rv = (*p->e_func)(clientp); 3911ae08745Sheppo 3921ae08745Sheppo return (exit_daemon_cmd(clientp, rv)); 3931ae08745Sheppo 3941ae08745Sheppo } 3951ae08745Sheppo 3961ae08745Sheppo /* vntsd_set_telnet_options() - change telnet client to character mode. */ 3971ae08745Sheppo int 3981ae08745Sheppo vntsd_set_telnet_options(int fd) 3991ae08745Sheppo { 4001ae08745Sheppo /* set client telnet options */ 4011ae08745Sheppo uint8_t buf[] = {IAC, DONT, LINEMODE, IAC, WILL, SUPRESS, IAC, WILL, 4021ae08745Sheppo TEL_ECHO, IAC, DONT, TERM_TYPE, IAC, DONT, TERM_SP, 4031ae08745Sheppo IAC, DONT, STATUS, IAC, DONT, FC, IAC, DONT, TM, IAC, DONT, ENV, 4041ae08745Sheppo IAC, DONT, WIN_SIZE}; 4051ae08745Sheppo 4061ae08745Sheppo return (vntsd_write_fd(fd, (char *)buf, 30)); 4071ae08745Sheppo } 4081ae08745Sheppo 4091ae08745Sheppo /* vntsd_telnet_cmd() process telnet commands */ 4101ae08745Sheppo int 4111ae08745Sheppo vntsd_telnet_cmd(vntsd_client_t *clientp, char c) 4121ae08745Sheppo { 4131ae08745Sheppo uint8_t buf[4]; 4141ae08745Sheppo char cmd; 4151ae08745Sheppo int rv = VNTSD_STATUS_CONTINUE; 4161ae08745Sheppo 4171ae08745Sheppo bzero(buf, 4); 4181ae08745Sheppo 4191ae08745Sheppo if ((uint8_t)c != IAC) { 4201ae08745Sheppo /* not telnet cmd */ 4211ae08745Sheppo return (VNTSD_SUCCESS); 4221ae08745Sheppo } 4231ae08745Sheppo 4241ae08745Sheppo if ((rv = vntsd_read_char(clientp, &cmd)) != VNTSD_SUCCESS) { 4251ae08745Sheppo return (rv); 4261ae08745Sheppo } 4271ae08745Sheppo 428a93081c1SChris Gerhard if ((uint8_t)cmd == WILL || (uint8_t)cmd == WONT || 429a93081c1SChris Gerhard (uint8_t)cmd == DO || (uint8_t)cmd == DONT) { 4301ae08745Sheppo if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) { 4311ae08745Sheppo return (rv); 4321ae08745Sheppo } 433823fe29bSdtse } 4341ae08745Sheppo 4351ae08745Sheppo 4361ae08745Sheppo switch ((uint8_t)cmd) { 4371ae08745Sheppo 4381ae08745Sheppo case WILL: 4391ae08745Sheppo 4401ae08745Sheppo switch ((uint8_t)c) { 4411ae08745Sheppo case TEL_ECHO: 4421ae08745Sheppo case SUPRESS: 4431ae08745Sheppo case LINEMODE: 4441ae08745Sheppo break; 4451ae08745Sheppo default: 4461ae08745Sheppo syslog(LOG_ERR, "not support telnet WILL %x\n", c); 4471ae08745Sheppo break; 4481ae08745Sheppo } 4491ae08745Sheppo break; 4501ae08745Sheppo 4511ae08745Sheppo case WONT: 4521ae08745Sheppo 4531ae08745Sheppo switch ((uint8_t)c) { 4541ae08745Sheppo case TEL_ECHO: 4551ae08745Sheppo case SUPRESS: 4561ae08745Sheppo case LINEMODE: 4571ae08745Sheppo default: 4581ae08745Sheppo syslog(LOG_ERR, "not support telnet WONT %x\n", c); 4591ae08745Sheppo break; 4601ae08745Sheppo } 4611ae08745Sheppo break; 4621ae08745Sheppo 4631ae08745Sheppo case DO: 4641ae08745Sheppo case DONT: 4651ae08745Sheppo 4661ae08745Sheppo buf[0] = IAC; 4671ae08745Sheppo buf[1] = WILL; 4681ae08745Sheppo buf[2] = c; 4691ae08745Sheppo rv = vntsd_write_client(clientp, (char *)buf, 3); 4701ae08745Sheppo 4711ae08745Sheppo break; 4721ae08745Sheppo 4731ae08745Sheppo case BRK: 4741ae08745Sheppo 4751ae08745Sheppo /* send break to vcc */ 4761ae08745Sheppo rv = genbrk(clientp); 4771ae08745Sheppo break; 4781ae08745Sheppo 4791ae08745Sheppo case IP: 4801ae08745Sheppo 4811ae08745Sheppo break; 4821ae08745Sheppo 483a93081c1SChris Gerhard case AYT: { 484a93081c1SChris Gerhard static char aytresp[] = "vntsd here"; 4851ae08745Sheppo 486a93081c1SChris Gerhard rv = vntsd_write_client(clientp, aytresp, 487a93081c1SChris Gerhard sizeof (aytresp) - 1); 4881ae08745Sheppo break; 489a93081c1SChris Gerhard } 4901ae08745Sheppo 4911ae08745Sheppo case HT: 492a93081c1SChris Gerhard case NOP: 4931ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 4941ae08745Sheppo 4951ae08745Sheppo default: 496a93081c1SChris Gerhard syslog(LOG_ERR, "not support telnet ctrl %2.2x\n", 0xff & cmd); 4971ae08745Sheppo break; 4981ae08745Sheppo } 4991ae08745Sheppo 5001ae08745Sheppo if (rv == VNTSD_SUCCESS) { 5011ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 5021ae08745Sheppo } else { 5031ae08745Sheppo return (rv); 5041ae08745Sheppo } 5051ae08745Sheppo } 5061ae08745Sheppo 5071ae08745Sheppo 5081ae08745Sheppo /* 5091ae08745Sheppo * vntsd_ctrl_cmd() - control keys 5101ae08745Sheppo * read and write suspend are supported. 5111ae08745Sheppo */ 5121ae08745Sheppo int 5131ae08745Sheppo vntsd_ctrl_cmd(vntsd_client_t *clientp, char c) 5141ae08745Sheppo { 5151ae08745Sheppo int cmd; 5161ae08745Sheppo 5171ae08745Sheppo D3(stderr, "t@%d vntsd_ctrl_cmd%d %d\n", thr_self(), 5181ae08745Sheppo clientp->cons->vcc_fd, clientp->sockfd); 5191ae08745Sheppo 5201ae08745Sheppo if ((c != START) && (c != STOP)) { 5211ae08745Sheppo /* not a supported control command */ 5221ae08745Sheppo return (VNTSD_SUCCESS); 5231ae08745Sheppo } 5241ae08745Sheppo 5251ae08745Sheppo if (c == START) { 5261ae08745Sheppo D3(stderr, "t@%d client restart\n", thr_self()); 5271ae08745Sheppo 5281ae08745Sheppo /* send resume read */ 5291ae08745Sheppo cmd = 1; 5301ae08745Sheppo 5311ae08745Sheppo if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) { 5321ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 5331ae08745Sheppo } 5341ae08745Sheppo 5351ae08745Sheppo } 5361ae08745Sheppo 5371ae08745Sheppo if (c == STOP) { 5381ae08745Sheppo D3(stderr, "t@%d client suspend\n", thr_self()); 5391ae08745Sheppo 5401ae08745Sheppo /* send suspend read */ 5411ae08745Sheppo cmd = 0; 5421ae08745Sheppo 5431ae08745Sheppo if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) { 5441ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 5451ae08745Sheppo } 5461ae08745Sheppo 5471ae08745Sheppo } 5481ae08745Sheppo 5491ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 5501ae08745Sheppo } 551