|
|
1.1 root 1: /* telgate.cpp */
2:
3: /* Synchronet telnet gateway routines */
4:
1.1.1.2 ! root 5: /* $Id: telgate.cpp,v 1.26 2004/12/30 02:57:00 rswindell Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
1.1.1.2 ! root 11: * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39: #include "telnet.h"
40:
41: void sbbs_t::telnet_gate(char* destaddr, ulong mode)
42: {
43: char* p;
44: uchar buf[512];
45: int i;
46: int rd;
1.1.1.2 ! root 47: uint attempts;
1.1 root 48: ulong l;
49: bool gotline;
50: ushort port;
51: ulong ip_addr;
52: ulong save_console;
53: SOCKET remote_socket;
54: SOCKADDR_IN addr;
55:
56: if(mode&TG_RLOGIN)
57: port=513;
58: else
59: port=IPPORT_TELNET;
60:
61: p=strchr(destaddr,':');
62: if(p!=NULL) {
63: *p=0;
64: port=atoi(p+1);
65: }
66:
67: ip_addr=resolve_ip(destaddr);
1.1.1.2 ! root 68: if(ip_addr==INADDR_NONE) {
! 69: lprintf(LOG_NOTICE,"!TELGATE Failed to resolve address: %s",destaddr);
! 70: bprintf("!Failed to resolve address: %s\r\n",destaddr);
1.1 root 71: return;
72: }
73:
74: if((remote_socket = open_socket(SOCK_STREAM)) == INVALID_SOCKET) {
75: errormsg(WHERE,ERR_OPEN,"socket",0);
76: return;
77: }
78:
79: memset(&addr,0,sizeof(addr));
1.1.1.2 ! root 80: addr.sin_addr.s_addr = htonl(startup->telnet_interface);
1.1 root 81: addr.sin_family = AF_INET;
82:
83: if((i=bind(remote_socket, (struct sockaddr *) &addr, sizeof (addr)))!=0) {
1.1.1.2 ! root 84: lprintf(LOG_NOTICE,"!TELGATE ERROR %d (%d) binding to socket %d",i, ERROR_VALUE, remote_socket);
! 85: bprintf("!ERROR %d (%d) binding to socket\r\n",i, ERROR_VALUE);
1.1 root 86: close_socket(remote_socket);
87: return;
88: }
89:
90: memset(&addr,0,sizeof(addr));
91: addr.sin_addr.s_addr = ip_addr;
92: addr.sin_family = AF_INET;
93: addr.sin_port = htons(port);
94:
95: if((i=connect(remote_socket, (struct sockaddr *)&addr, sizeof(addr)))!=0) {
1.1.1.2 ! root 96: lprintf(LOG_NOTICE,"!TELGATE ERROR %d (%d) connecting to server: %s"
1.1 root 97: ,i,ERROR_VALUE, destaddr);
1.1.1.2 ! root 98: bprintf("!ERROR %d (%d) connecting to server: %s\r\n"
1.1 root 99: ,i,ERROR_VALUE, destaddr);
1.1.1.2 ! root 100: close_socket(remote_socket);
1.1 root 101: return;
102: }
103:
104: l=1;
105:
106: if((i = ioctlsocket(remote_socket, FIONBIO, &l))!=0) {
1.1.1.2 ! root 107: lprintf(LOG_NOTICE,"!TELGATE ERROR %d (%d) disabling socket blocking"
1.1 root 108: ,i, ERROR_VALUE);
1.1.1.2 ! root 109: close_socket(remote_socket);
1.1 root 110: return;
111: }
112:
1.1.1.2 ! root 113: lprintf(LOG_INFO,"Node %d %s gate to %s port %d on socket %d"
1.1 root 114: ,cfg.node_num
115: ,mode&TG_RLOGIN ? "RLogin" : "Telnet"
116: ,destaddr,port,remote_socket);
117:
118: if(mode&(TG_PASSTHRU|TG_RLOGIN))
119: telnet_mode|=TELNET_MODE_GATE; // Pass-through telnet commands
120:
121: if(!(mode&TG_CTRLKEYS))
122: console|=CON_RAW_IN;
123:
124: if(mode&TG_RLOGIN) {
125: p=(char*)buf;
126: *(p++)=0;
1.1.1.2 ! root 127: p+=sprintf(p,"%s",useron.alias);
! 128: p++; // Add NULL
! 129: p+=sprintf(p,"%s",useron.name);
! 130: p++; // Add NULL
! 131: p+=sprintf(p,"%s/57600",terminal);
! 132: p++; // Add NULL
1.1 root 133: l=p-(char*)buf;
1.1.1.2 ! root 134: sendsocket(remote_socket,(char*)buf,l);
1.1 root 135: }
136:
1.1.1.2 ! root 137: /* This is required for gating to Unix telnetd */
! 138: if(mode&TG_NOTERMTYPE)
! 139: request_telnet_opt(TELNET_DONT,TELNET_TERM_TYPE); // Re-negotiation of terminal type
! 140:
! 141: /* Text/NVT mode by default */
! 142: request_telnet_opt(TELNET_DONT,TELNET_BINARY_TX);
! 143:
1.1 root 144: while(online) {
1.1.1.2 ! root 145: if(!(mode&TG_NOCHKTIME))
! 146: gettimeleft();
1.1 root 147: rd=RingBufRead(&inbuf,buf,sizeof(buf));
148: if(rd) {
1.1.1.2 ! root 149: #if 0
! 150: if(memchr(buf,TELNET_IAC,rd)) {
! 151: char dump[2048];
! 152: dump[0];
! 153: p=dump;
! 154: for(int i=0;i<rd;i++)
! 155: p+=sprintf(p,"%u ",buf[i]);
! 156: lprintf(LOG_DEBUG,"Node %d Telnet cmd from client: %s", cfg.node_num, dump);
! 157: }
! 158: #endif
! 159: if(telnet_remote_option[TELNET_BINARY_TX]!=TELNET_WILL) {
1.1 root 160: if(*buf==0x1d) { // ^]
161: save_console=console;
162: console&=~CON_RAW_IN; // Allow Ctrl-U/Ctrl-P
163: CRLF;
164: while(online) {
165: SYNC;
166: mnemonics("\1n\r\n\1h\1bTelnet Gate: \1y~D\1wisconnect, "
167: "\1y~E\1wcho toggle, \1y~L\1wist Users, \1y~P\1wrivate message, "
168: "\1y~Q\1wuit: ");
169: switch(getkeys("DELPQ",0)) {
170: case 'D':
171: closesocket(remote_socket);
172: break;
173: case 'E':
174: mode^=TG_ECHO;
175: bprintf(text[EchoIsNow]
176: ,mode&TG_ECHO
177: ? text[ON]:text[OFF]);
178: continue;
179: case 'L':
180: whos_online(true);
181: continue;
182: case 'P':
183: nodemsg();
184: continue;
185: }
186: break;
187: }
188: attr(LIGHTGRAY);
189: console=save_console;
190: }
1.1.1.2 ! root 191: else if(*buf<' ' && mode&TG_CTRLKEYS)
! 192: handle_ctrlkey(*buf, K_NONE);
1.1 root 193: gotline=false;
194: if(mode&TG_LINEMODE && buf[0]!='\r') {
195: ungetkey(buf[0]);
196: l=K_CHAT;
197: if(!(mode&TG_ECHO))
198: l|=K_NOECHO;
199: rd=getstr((char*)buf,sizeof(buf)-1,l);
200: if(!rd)
201: continue;
202: strcat((char*)buf,crlf);
203: rd+=2;
204: gotline=true;
205: }
206: if(mode&TG_CRLF && buf[rd-1]=='\r')
207: buf[rd++]='\n';
208: if(!gotline && mode&TG_ECHO) {
209: RingBufWrite(&outbuf,buf,rd);
210: }
211: }
1.1.1.2 ! root 212: for(attempts=0;attempts<60 && online; attempts++) /* added retry loop here, Jan-20-2003 */
! 213: {
! 214: if((i=sendsocket(remote_socket,(char*)buf,rd))>=0)
! 215: break;
! 216: if(ERROR_VALUE!=EWOULDBLOCK)
! 217: break;
! 218: mswait(500);
! 219: }
! 220: if(i<0) {
! 221: lprintf(LOG_NOTICE,"!TELGATE ERROR %d sending on socket %d",ERROR_VALUE,remote_socket);
1.1 root 222: break;
223: }
224: }
225: rd=recv(remote_socket,(char*)buf,sizeof(buf),0);
226: if(rd<0) {
227: if(ERROR_VALUE==EWOULDBLOCK) {
228: if(mode&TG_NODESYNC) {
229: SYNC;
1.1.1.2 ! root 230: } else {
! 231: // Check if the node has been interrupted
! 232: getnodedat(cfg.node_num,&thisnode,0);
! 233: if(thisnode.misc&NODE_INTR)
! 234: break;
1.1 root 235: }
1.1.1.2 ! root 236: YIELD();
1.1 root 237: continue;
238: }
1.1.1.2 ! root 239: lprintf(LOG_NOTICE,"!TELGATE ERROR %d receiving on socket %d",ERROR_VALUE,remote_socket);
1.1 root 240: break;
241: }
242: if(!rd) {
1.1.1.2 ! root 243: lprintf(LOG_INFO,"Node %d Telnet gate disconnected",cfg.node_num);
1.1 root 244: break;
245: }
1.1.1.2 ! root 246: #if 0
! 247: if(memchr(buf,TELNET_IAC,rd)) {
! 248: char dump[2048];
! 249: dump[0];
! 250: p=dump;
! 251: for(int i=0;i<rd;i++)
! 252: p+=sprintf(p,"%u ",buf[i]);
! 253: lprintf(LOG_DEBUG,"Node %d Telnet cmd from remote: %s", cfg.node_num, dump);
! 254: }
! 255: #endif
1.1 root 256: RingBufWrite(&outbuf,buf,rd);
257: }
258: console&=~CON_RAW_IN;
259: telnet_mode&=~TELNET_MODE_GATE;
260:
261: /* Disable Telnet Terminal Echo */
1.1.1.2 ! root 262: request_telnet_opt(TELNET_WILL,TELNET_ECHO);
1.1 root 263:
264: close_socket(remote_socket);
265:
1.1.1.2 ! root 266: lprintf(LOG_INFO,"Node %d Telnet gate to %s finished",cfg.node_num,destaddr);
1.1 root 267: }
268:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.