/****************************************************************************** * This file is part of a software distribution, which is furnished under the * * terms of a license. Use of this software by any means is subject to this * * license and signifies the acceptance of the licensing terms stated * * therein. Please see the file LICENSE in the top-level directory of this * * software distribution for detailed copyright disclaimers and licensing * * terms. * ****************************************************************************** * Copryight (c) by Andreas S. Wetzel - All rights reserved. * ******************************************************************************/ /* $Id: vd_telproto.c,v 1.2 2001/03/19 14:54:06 mickey Exp $ */ #include #include #include #if HAVE_SYS_SELECT_H #include #endif /*** Globals ***/ char *topts[NTOPTS+1] = { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND_LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON", 0 }; u_char subopt_buf[SUB_BUFSIZE]; u_char *sub_bufptr = &subopt_buf[0]; u_char *sub_endptr = &subopt_buf[0]; u_short tel_option[256]; u_short do_dont_response[256]; u_short will_wont_response[256]; /*** Externals ***/ extern VP vp; extern VD vd; /*** Code ***/ void send_do(int opcode, int bypass) { if(!bypass) { /* Don't send request if already in */ /* requested state and no responses */ /* open, or if we already requested */ /* that state. */ if((!do_dont_response[opcode] && his_state_is_will(opcode)) || his_want_state_is_will(opcode)) { return; } set_his_want_state_will(opcode); ++do_dont_response[opcode]; } printf("%c%c%c", IAC, DO, opcode); if(TOPT_OK(opcode)) log(VLOG_DEBUG, "(SND) DO %s", TOPT(opcode)); else log(VLOG_DEBUG, "(SND) DO %d", opcode); } void send_dont(int opcode, int bypass) { if(!bypass) { /* Don't send request if already in */ /* requested state and no responses */ /* open, or if we already requested */ /* that state. */ if((!do_dont_response[opcode] && his_state_is_wont(opcode)) || his_want_state_is_wont(opcode)) { return; } set_his_want_state_wont(opcode); ++do_dont_response[opcode]; } printf("%c%c%c", IAC, DONT, opcode); if(TOPT_OK(opcode)) log(VLOG_DEBUG, "(SND) DONT %s", TOPT(opcode)); else log(VLOG_DEBUG, "(SND) DONT %d", opcode); } void send_will(int opcode, int bypass) { if(!bypass) { /* Don't send request if already in */ /* requested state and no responses */ /* open, or if we already requested */ /* that state. */ if((!will_wont_response[opcode] && my_state_is_will(opcode)) || my_want_state_is_will(opcode)) { return; } set_my_want_state_will(opcode); ++will_wont_response[opcode]; } printf("%c%c%c", IAC, WILL, opcode); if(TOPT_OK(opcode)) log(VLOG_DEBUG, "(SND) WILL %s", TOPT(opcode)); else log(VLOG_DEBUG, "(SND) WILL %d", opcode); } void send_wont(int opcode, int bypass) { if(!bypass) { /* Don't send request if already in */ /* requested state and no responses */ /* open, or if we already requested */ /* that state. */ if((!will_wont_response[opcode] && my_state_is_wont(opcode)) || my_want_state_is_wont(opcode)) { return; } set_my_want_state_wont(opcode); ++will_wont_response[opcode]; } printf("%c%c%c", IAC, WONT, opcode); if(TOPT_OK(opcode)) log(VLOG_DEBUG, "(SND) WONT %s", TOPT(opcode)); else log(VLOG_DEBUG, "(SND) WONT %d", opcode); } int request_termtype(void) { send_do(TELOPT_TTYPE, 0); send_do(TELOPT_NAWS, 0); while(his_will_wont_differs(TELOPT_TTYPE) || his_will_wont_differs(TELOPT_NAWS)) { if(cmd_loop() == -1) return(-1); } if(his_state_is_will(TELOPT_TTYPE)) { printf("%c%c%c%c%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE); while(!vd.emu_ok) { if(cmd_loop() == -1) return(-1); } } else { strcpy(vd.env_term, DEFAULT_TTYPE); vp.emulation = (char *)&vd.env_term; vd.emu_ok = 0xff; log(VLOG_INFO, "Client side does not support TTYPE option - defaulting to %s.", vp.emulation); } #if 0 if(his_state_is_will(TELOPT_NAWS)) { printf("%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, TELQUAL_SEND, IAC, SE); } #endif return(0); } int cmd_loop(void) { fd_set rfdset; int ret, c; u_char rcvbuf[512]; u_char *bufptr = &rcvbuf[0]; struct timeval tm; tm.tv_sec = 0; tm.tv_usec = 350000; /* 0.2 sec */ FD_ZERO(&rfdset); FD_SET(0, &rfdset); if((ret = select(1, (fd_set *) &rfdset, (fd_set *) NULL, (fd_set *) NULL,(struct timeval *)&tm)) == -1) { log(VLOG_ERR, "cmd_loop(): error in select();"); return(-1); } else if(ret) { if(FD_ISSET(0, &rfdset)) { if((ret = read(0, &rcvbuf, 512)) == -1) { log(VLOG_ERR, "cmd_loop: read error (%s)", strerror(errno)); return(-1); } else if(!ret) { log(VLOG_ERR, "cmd_loop: broken pipe"); return(-1); } while(ret) { if((c = tel_filter(*bufptr++))) { log(VLOG_ERR, "cmd_loop(): unwanted user character $%02x", c); ungetc(c, stdin); } --ret; } } } #ifdef DEBUG else { log(VLOG_DEBUG, "cmd_loop(): Timeout"); } #endif return(0); }