void send_telnet_cmd(SOCKET sock, uchar cmd, uchar opt) { uchar buf[3]; buf[0]=TELNET_IAC; buf[1]=cmd; buf[2]=opt; if(debug_telnet) lprintf(LOG_DEBUG,"Sending telnet command: %s %s" ,telnet_cmd_desc(buf[1]),telnet_opt_desc(buf[2])); if(sendsocket(sock,buf,sizeof(buf))!=sizeof(buf) && debug_telnet) lprintf(LOG_ERR,"FAILED"); }
static void send_telnet_cmd(uchar cmd, uchar opt) { char buf[16]; if(cmd<TELNET_WILL) { if(debug_telnet) lprintf(LOG_INFO,"TX Telnet command: %s" ,telnet_cmd_desc(cmd)); sprintf(buf,"%c%c",TELNET_IAC,cmd); sendsocket(sock,buf,2); } else { if(debug_telnet) lprintf(LOG_INFO,"TX Telnet command: %s %s" ,telnet_cmd_desc(cmd), telnet_opt_desc(opt)); sprintf(buf,"%c%c%c",TELNET_IAC,cmd,opt); sendsocket(sock,buf,3); } }
BYTE* telnet_interpret(BYTE* inbuf, int inlen, BYTE* outbuf, int *outlen) { BYTE command; BYTE option; BYTE* first_iac; int i; if(inlen<1) { *outlen=0; return(inbuf); /* no length? No interpretation */ } first_iac=(BYTE*)memchr(inbuf, TELNET_IAC, inlen); if(!telnet_cmdlen && first_iac==NULL) { *outlen=inlen; return(inbuf); /* no interpretation needed */ } if(first_iac!=NULL) { *outlen=first_iac-inbuf; memcpy(outbuf, inbuf, *outlen); } else *outlen=0; for(i=*outlen;i<inlen;i++) { if(inbuf[i]==TELNET_IAC && telnet_cmdlen==1) { /* escaped 255 */ telnet_cmdlen=0; outbuf[(*outlen)++]=TELNET_IAC; continue; } if(inbuf[i]==TELNET_IAC || telnet_cmdlen) { if(telnet_cmdlen<sizeof(telnet_cmd)) telnet_cmd[telnet_cmdlen++]=inbuf[i]; command = telnet_cmd[1]; option = telnet_cmd[2]; if(telnet_cmdlen>=2 && command==TELNET_SB) { if(inbuf[i]==TELNET_SE && telnet_cmd[telnet_cmdlen-2]==TELNET_IAC) { if(debug_telnet) lprintf(LOG_INFO,"RX Telnet sub-negotiation command: %s" ,telnet_opt_desc(option)); /* sub-option terminated */ if(option==TELNET_TERM_TYPE && telnet_cmd[3]==TELNET_TERM_SEND) { BYTE buf[32]; int len=sprintf(buf,"%c%c%c%c%s%c%c" ,TELNET_IAC,TELNET_SB ,TELNET_TERM_TYPE,TELNET_TERM_IS ,termtype ,TELNET_IAC,TELNET_SE); if(debug_telnet) lprintf(LOG_INFO,"TX Telnet command: Terminal Type is %s", termtype); sendsocket(sock,buf,len); /* request_telnet_opt(TELNET_WILL, TELNET_TERM_SPEED); */ } else if(option==TELNET_TERM_SPEED && telnet_cmd[3]==TELNET_TERM_SEND) { BYTE buf[32]; int len=sprintf(buf,"%c%c%c%c%s%c%c" ,TELNET_IAC,TELNET_SB ,TELNET_TERM_SPEED,TELNET_TERM_IS ,termspeed ,TELNET_IAC,TELNET_SE); if(debug_telnet) lprintf(LOG_INFO,"TX Telnet command: Terminal Speed is %s", termspeed); sendsocket(sock,buf,len); } telnet_cmdlen=0; } } else if(telnet_cmdlen==2 && inbuf[i]<TELNET_WILL) { telnet_cmdlen=0; } else if(telnet_cmdlen>=3) { /* telnet option negotiation */ if(debug_telnet) lprintf(LOG_INFO,"RX Telnet command: %s %s" ,telnet_cmd_desc(command),telnet_opt_desc(option)); if(command==TELNET_DO || command==TELNET_DONT) { /* local options */ if(telnet_local_option[option]!=command) { switch(option) { case TELNET_BINARY_TX: case TELNET_ECHO: case TELNET_TERM_TYPE: case TELNET_TERM_SPEED: case TELNET_SUP_GA: telnet_local_option[option]=command; send_telnet_cmd(telnet_opt_ack(command),option); break; case TELNET_SEND_LOCATION: if(command==TELNET_DO) { BYTE buf[128]; int len=safe_snprintf(buf,sizeof(buf),"%c%c%c%s %s%c%c" ,TELNET_IAC,TELNET_SB ,TELNET_SEND_LOCATION ,cid_number, cid_name ,TELNET_IAC,TELNET_SE); if(debug_telnet) lprintf(LOG_INFO,"TX Telnet command: Location is %s %s", cid_number, cid_name); sendsocket(sock,buf,len); } else send_telnet_cmd(telnet_opt_ack(command),option); break; default: /* unsupported local options */ if(command==TELNET_DO) /* NAK */ send_telnet_cmd(telnet_opt_nak(command),option); break; } } } else { /* WILL/WONT (remote options) */ if(telnet_remote_option[option]!=command) { switch(option) { case TELNET_BINARY_TX: case TELNET_ECHO: case TELNET_TERM_TYPE: case TELNET_SUP_GA: telnet_remote_option[option]=command; send_telnet_cmd(telnet_opt_ack(command),option); break; default: /* unsupported remote options */ if(command==TELNET_WILL) /* NAK */ send_telnet_cmd(telnet_opt_nak(command),option); break; } } } telnet_cmdlen=0; } } else outbuf[(*outlen)++]=inbuf[i]; } return(outbuf); }
int recv_byte(void* unused, unsigned timeout) { int i; long t; uchar ch; fd_set socket_set; time_t end; struct timeval tv; static uchar telnet_cmd; static int telnet_cmdlen; end=msclock()+(timeout*MSCLOCKS_PER_SEC); while(!terminate) { FD_ZERO(&socket_set); #ifdef __unix__ if(stdio) FD_SET(STDIN_FILENO,&socket_set); else #endif FD_SET(sock,&socket_set); if((t=end-msclock())<0) t=0; tv.tv_sec=t/MSCLOCKS_PER_SEC; tv.tv_usec=0; if((i=select(sock+1,&socket_set,NULL,NULL,&tv))<1) { if(i==SOCKET_ERROR) { lprintf(LOG_ERR,"ERROR %d selecting socket", ERROR_VALUE); } if(timeout) lprintf(LOG_WARNING,"Receive timeout (%u seconds)", timeout); return(NOINP); } #ifdef __unix__ if(stdio) i=read(STDIN_FILENO,&ch,sizeof(ch)); else #endif i=recv(sock,&ch,sizeof(ch),0); if(i!=sizeof(ch)) { if(i==0) { lprintf(LOG_WARNING,"Socket Disconnected"); } else lprintf(LOG_ERR,"recv error %d (%d)",i,ERROR_VALUE); return(NOINP); } if(telnet) { if(ch==TELNET_IAC) { #if DEBUG_TELNET lprintf(LOG_DEBUG,"T<%s> ",telnet_cmd_desc(ch)); #endif if(telnet_cmdlen==0) { telnet_cmdlen=1; continue; } if(telnet_cmdlen==1) { telnet_cmdlen=0; if(debug_rx) lprintf(LOG_DEBUG,"RX: %s",chr(TELNET_IAC)); return(TELNET_IAC); } } if(telnet_cmdlen) { telnet_cmdlen++; #if DEBUG_TELNET if(telnet_cmdlen==2) lprintf(LOG_DEBUG,"T<%s> ",telnet_cmd_desc(ch)); else lprintf(LOG_DEBUG,"T<%s> ",telnet_opt_desc(ch)); #endif if(debug_telnet && telnet_cmdlen==3) lprintf(LOG_DEBUG,"Received telnet command: %s %s" ,telnet_cmd_desc(telnet_cmd),telnet_opt_desc(ch)); if(telnet_cmdlen==3 && telnet_cmd==TELNET_DO) send_telnet_cmd(sock, TELNET_WILL,ch); /* else if(telnet_cmdlen==3 && telnet_cmd==TELNET_WILL) send_telnet_cmd(sock, TELNET_DO,ch); */ telnet_cmd=ch; if((telnet_cmdlen==2 && ch<TELNET_WILL) || telnet_cmdlen>2) { telnet_cmdlen=0; /* Code disabled. Why? ToDo */ /* break; */ } continue; } } if(debug_rx) lprintf(LOG_DEBUG,"RX: %s",chr(ch)); return(ch); } return(NOINP); }