|
|
1.1 root 1: /* telgate.cpp */
2:
3: /* Synchronet telnet gateway routines */
4:
5: /* $Id: telgate.cpp,v 1.6 2000/10/31 04:14:51 rswindell Exp $ */
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: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
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: extern "C" {
42: int open_socket(int);
43: int close_socket(int);
44: }
45:
46: u_long resolve_ip(char *addr)
47: {
48: HOSTENT* host;
49:
50: if(isdigit(addr[0]))
51: return(inet_addr(addr));
52: if ((host=gethostbyname(addr))==NULL)
53: return(0);
54: return(*((ulong*)host->h_addr_list[0]));
55: }
56:
57: void sbbs_t::telnet_gate(char* destaddr, ulong mode)
58: {
59: char* p;
60: char str[128];
61: uchar buf[512];
62: int i;
63: int rd;
64: ulong l;
65: bool gotline;
66: ushort port;
67: ulong ip_addr;
68: ulong save_console;
69: SOCKET remote_socket;
70: SOCKADDR_IN addr;
71:
72: if(mode&TG_RLOGIN)
73: port=513;
74: else
75: port=IPPORT_TELNET;
76:
77: p=strchr(destaddr,':');
78: if(p!=NULL) {
79: *p=0;
80: port=atoi(p+1);
81: }
82:
83: ip_addr=resolve_ip(destaddr);
84: if(!ip_addr) {
85: lprintf("!Failed to resolve address: %s",destaddr);
86: bprintf("!Failed to resolve address: %s\n",destaddr);
87: return;
88: }
89:
90: if((remote_socket = open_socket(SOCK_STREAM)) == INVALID_SOCKET) {
91: errormsg(WHERE,ERR_OPEN,"socket",0);
92: return;
93: }
94:
95: memset(&addr,0,sizeof(addr));
96: addr.sin_addr.s_addr = htonl(cfg.startup->telnet_interface);
97: addr.sin_family = AF_INET;
98:
99: if((i=bind(remote_socket, (struct sockaddr *) &addr, sizeof (addr)))!=0) {
100: close_socket(remote_socket);
101: lprintf("!ERROR %d (%d) binding to socket %d",i, ERROR_VALUE, socket);
102: bprintf("!ERROR %d (%d) binding to socket\n",i, ERROR_VALUE);
103: return;
104: }
105:
106: memset(&addr,0,sizeof(addr));
107: addr.sin_addr.s_addr = ip_addr;
108: addr.sin_family = AF_INET;
109: addr.sin_port = htons(port);
110:
111: if((i=connect(remote_socket, (struct sockaddr *)&addr, sizeof(addr)))!=0) {
112: close_socket(remote_socket);
113: lprintf("!ERROR %d (%d) connecting to server: %s"
114: ,i,ERROR_VALUE, destaddr);
115: bprintf("!ERROR %d (%d) connecting to server: %s\n"
116: ,i,ERROR_VALUE, destaddr);
117: return;
118: }
119:
120: l=1;
121:
122: if((i = ioctlsocket(remote_socket, FIONBIO, &l))!=0) {
123: close_socket(remote_socket);
124: lprintf("!ERROR %d (%d) disabling socket blocking"
125: ,i, ERROR_VALUE);
126: return;
127: }
128:
129: lprintf("Node %d %s gate to %s port %d on socket %d"
130: ,cfg.node_num
131: ,mode&TG_RLOGIN ? "RLogin" : "Telnet"
132: ,destaddr,port,remote_socket);
133:
134: if(mode&(TG_PASSTHRU|TG_RLOGIN))
135: telnet_mode|=TELNET_MODE_GATE; // Pass-through telnet commands
136:
137: if(!(mode&TG_CTRLKEYS))
138: console|=CON_RAW_IN;
139:
140: if(mode&TG_RLOGIN) {
141: p=(char*)buf;
142: *(p++)=0;
143: strcpy(p,useron.alias);
144: p+=strlen(p)+1;
145: strcpy(p,useron.name);
146: p+=strlen(p)+1;
147: strcpy(p,"vt100/57600");
148: p+=strlen(p)+1;
149: l=p-(char*)buf;
150: send(remote_socket,(char*)buf,l,0);
151: }
152:
153: while(online) {
154: gettimeleft();
155: rd=RingBufRead(&inbuf,buf,sizeof(buf));
156: if(rd) {
157: if(!(telnet_mode&TELNET_MODE_BIN_RX)) {
158: if(*buf==0x1d) { // ^]
159: save_console=console;
160: console&=~CON_RAW_IN; // Allow Ctrl-U/Ctrl-P
161: CRLF;
162: while(online) {
163: SYNC;
164: mnemonics("\1n\r\n\1h\1bTelnet Gate: \1y~D\1wisconnect, "
165: "\1y~E\1wcho toggle, \1y~L\1wist Users, \1y~P\1wrivate message, "
166: "\1y~Q\1wuit: ");
167: switch(getkeys("DELPQ",0)) {
168: case 'D':
169: closesocket(remote_socket);
170: break;
171: case 'E':
172: mode^=TG_ECHO;
173: bprintf(text[EchoIsNow]
174: ,mode&TG_ECHO
175: ? text[ON]:text[OFF]);
176: continue;
177: case 'L':
178: whos_online(true);
179: continue;
180: case 'P':
181: nodemsg();
182: continue;
183: }
184: break;
185: }
186: attr(LIGHTGRAY);
187: console=save_console;
188: }
189: gotline=false;
190: if(mode&TG_LINEMODE && buf[0]!='\r') {
191: ungetkey(buf[0]);
192: l=K_CHAT;
193: if(!(mode&TG_ECHO))
194: l|=K_NOECHO;
195: rd=getstr((char*)buf,sizeof(buf)-1,l);
196: if(!rd)
197: continue;
198: strcat((char*)buf,crlf);
199: rd+=2;
200: gotline=true;
201: }
202: if(mode&TG_CRLF && buf[rd-1]=='\r')
203: buf[rd++]='\n';
204: if(!gotline && mode&TG_ECHO) {
205: RingBufWrite(&outbuf,buf,rd);
206: sem_post(&output_sem);
207: }
208: }
209: if((i=send(remote_socket,(char*)buf,rd,0))<0) {
210: lprintf("!TELGATE ERROR %d sending on socket %d",ERROR_VALUE,remote_socket);
211: break;
212: }
213: }
214: rd=recv(remote_socket,(char*)buf,sizeof(buf),0);
215: if(rd<0) {
216: if(ERROR_VALUE==EWOULDBLOCK) {
217: if(mode&TG_NODESYNC) {
218: SYNC;
219: }
220: mswait(1);
221: continue;
222: }
223: lprintf("!TELGATE ERROR %d receiving on socket %d",ERROR_VALUE,remote_socket);
224: break;
225: }
226: if(!rd) {
227: lprintf("Node %d Telnet gate disconnected",cfg.node_num);
228: break;
229: }
230: RingBufWrite(&outbuf,buf,rd);
231: sem_post(&output_sem);
232: }
233: console&=~CON_RAW_IN;
234: telnet_mode&=~TELNET_MODE_GATE;
235:
236: /* Disable Telnet Terminal Echo */
237: sprintf(str,"%c%c%c",TELNET_IAC,TELNET_WILL,TELNET_ECHO);
238: putcom(str,3);
239:
240: close_socket(remote_socket);
241:
242: lprintf("Node %d Telnet gate to %s finished",cfg.node_num,destaddr);
243: }
244:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.