00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <gc/gc.h>
00004 #include <stdarg.h>
00005 #include <unistd.h>
00006 #include <string.h>
00007 #include <sys/types.h>
00008 #include <sys/time.h>
00009 #include <sys/socket.h>
00010 #include <netinet/in.h>
00011 #include <netinet/ip.h>
00012 #include <netinet/tcp.h>
00013 #include <fcntl.h>
00014 #include <time.h>
00015 #include <event.h>
00016 #include <netdb.h>
00017 #include <signal.h>
00018 #define DEBUG
00019 #include <debug.h>
00020 #include <rbtree.h>
00021 #include "network.h"
00022 #include "telnet.h"
00023 #include "client.h"
00024
00025 static void telnet_send_req(DESC * client, int how, int request);
00026 static void telnet_send_subop(DESC * client, int how, int option);
00027 static void telnet_handle_will(DESC * client, int option);
00028 static void telnet_handle_wont(DESC * client, int option);
00029 static int telnet_handle_subop(DESC * client, unsigned char *buffer,
00030 int length);
00031
00032 int telnet_init(DESC * client)
00033 {
00034 dprintk("telnet initializing.");
00035 strncpy(client->termtype, "vt100", 16);
00036 client->telnet_win_width = 80;
00037 client->telnet_win_height = 25;
00038
00039 telnet_send_req(client, TELNET_DO, TELNET_OPT_TERMTYPE);
00040 telnet_send_req(client, TELNET_DO, TELNET_OPT_WINSIZE);
00041 return 1;
00042 }
00043
00044
00045 static void telnet_send_req(DESC * client, int how, int request)
00046 {
00047 unsigned char buffer[16] = { TELNET_IAC, how, request };
00048 network_write(client, (void *) buffer, 3);
00049 }
00050 static void telnet_send_subop(DESC * client, int option, int how)
00051 {
00052 unsigned char buffer[16] =
00053 { TELNET_IAC, TELNET_SB, option, how, TELNET_IAC, TELNET_SE };
00054 network_write(client, (void *) buffer, 6);
00055 }
00056
00057 static void telnet_handle_will(DESC * client, int option)
00058 {
00059 switch (option) {
00060 case TELNET_OPT_TERMTYPE:
00061 client->telnet_has_termtype = TSTATE_SUP;
00062 dprintk("client acknowledged TERMTYPE");
00063 break;
00064 case TELNET_OPT_WINSIZE:
00065 client->telnet_has_winsize = TSTATE_SUP;
00066 dprintk("client acknowledged WINSIZE");
00067 break;
00068 }
00069 }
00070
00071 static void telnet_handle_wont(DESC * client, int option)
00072 {
00073 switch (option) {
00074 case TELNET_OPT_TERMTYPE:
00075 client->telnet_has_termtype = TSTATE_UNSUP;
00076 strncpy(client->termtype, "vt100", 16);
00077 break;
00078 case TELNET_OPT_WINSIZE:
00079 client->telnet_has_winsize = TSTATE_UNSUP;
00080 client->telnet_win_width = 80;
00081 client->telnet_win_height = 25;
00082 break;
00083 }
00084 }
00085
00086 static void telnet_check_options(DESC * client)
00087 {
00088 if(client->telnet_has_termtype == TSTATE_SUP) {
00089 client->telnet_has_termtype = TSTATE_REQUEST;
00090 telnet_send_subop(client, TELNET_OPT_TERMTYPE, TELNET_SUB_REQUIRED);
00091 } else if(client->telnet_has_termtype == TSTATE_REQUEST) {
00092 client->telnet_has_termtype = TSTATE_UNSUP;
00093 }
00094
00095 if(client->telnet_has_winsize == TSTATE_SUP) {
00096 client->telnet_has_winsize = TSTATE_REQUEST;
00097 telnet_send_subop(client, TELNET_OPT_WINSIZE, TELNET_SUB_REQUIRED);
00098 } else if(client->telnet_has_winsize == TSTATE_REQUEST) {
00099 client->telnet_has_termtype = TSTATE_UNSUP;
00100 }
00101 }
00102
00103 static int telnet_handle_subop(DESC * client, unsigned char *buffer,
00104 int length)
00105 {
00106 int iter;
00107 if(buffer[1] != TELNET_SUB_SUPPLIED)
00108 dfail("unexpected reply in telnet suboption negotiation.");
00109 iter = 2;
00110 switch (buffer[0]) {
00111 case TELNET_OPT_TERMTYPE:
00112 memset(client->termtype, 0, 16);
00113 for(iter = 2; iter < length && iter < 18 && buffer[iter] != 0xFF;
00114 iter++) {
00115 client->termtype[iter - 2] = buffer[iter];
00116 }
00117 iter++;
00118 dprintk("Received Terminal Type '%s'", client->termtype);
00119 client->telnet_has_termtype = TSTATE_REPLIED;
00120 break;
00121 case TELNET_OPT_WINSIZE:
00122 client->telnet_win_width = buffer[2];
00123 client->telnet_win_height = buffer[4];
00124 iter = 6;
00125 dprintk("Received Window Size %dx%d", client->telnet_win_width,
00126 client->telnet_win_height);
00127 client->telnet_has_winsize = TSTATE_REPLIED;
00128 break;
00129 default:
00130 dfail("unexpected reply in telnet usboption negotiation.");
00131 }
00132 return iter;
00133 }
00134
00135 #define ring_avail(client) (client->ringtail > client->ringhead ? RING_LENGTH - client->ringtail + client->ringhead : \
00136 client->ringhead - client->ringtail)
00137 #define ring_char(client, x) (client->ringbuffer[(client->ringhead+x)%RING_LENGTH])
00138 #define ring_length(client) (client->ringtail >= client->ringhead ? client->ringtail - client->ringhead : \
00139 RING_LENGTH - client->ringhead + client->ringtail)
00140 #define ring_eat(client, x) (client->ringhead = (client->ringhead+x) % RING_LENGTH)
00141
00142 void telnet_read_ring(DESC * client)
00143 {
00144 int iter, complete;
00145 unsigned char subopt_buffer[32];
00146
00147 dprintk
00148 ("Ring Read started, input length = %d, ringhead = %d, ringtail = %d. ",
00149 ring_length(client), client->ringhead, client->ringtail);
00150
00151 while (ring_length(client) > 0) {
00152 dprintk
00153 ("Parsing data 0x%02x, %d bytes in ring, ringhead = %d, ringtail = %d",
00154 ring_char(client, 0), ring_length(client), client->ringhead,
00155 client->ringtail);
00156 switch (ring_char(client, 0)) {
00157 case TELNET_IAC:
00158 if(ring_length(client) < 2)
00159 return;
00160 dprintk("TELNET COMMADN %d", ring_char(client, 1));
00161 switch ((unsigned char) ring_char(client, 1)) {
00162 case TELNET_WILL:
00163 telnet_handle_will(client, ring_char(client, 2));
00164 ring_eat(client, 3);
00165 break;
00166 case TELNET_WONT:
00167 telnet_handle_wont(client, ring_char(client, 2));
00168 ring_eat(client, 3);
00169 break;
00170 case TELNET_SB:
00171 complete = 0;
00172 for(iter = 2; !complete && iter < ring_avail(client); iter++) {
00173 subopt_buffer[iter - 2] = ring_char(client, iter);
00174 if(ring_char(client, iter) == TELNET_SE) {
00175 telnet_handle_subop(client, subopt_buffer, iter - 2);
00176 complete = 1;
00177 ring_eat(client, iter + 1);
00178 }
00179 }
00180 if(!complete)
00181 return;
00182 break;
00183 case TELNET_IAC:
00184 client->inputbuffer[client->inputtail++] = TELNET_IAC;
00185 default:
00186 ring_eat(client, 2);
00187 break;
00188 }
00189 break;
00190 case 0:
00191 ring_eat(client, 1);
00192 break;
00193 case '\r':
00194 case '\n':
00195 if(ring_length(client) > 1 && (ring_char(client, 1) == '\r' ||
00196 ring_char(client, 1) == '\n')) {
00197 ring_eat(client, 1);
00198 }
00199 if(client->inputtail == 0) {
00200 ring_eat(client, 1);
00201 continue;
00202 }
00203 client->inputbuffer[client->inputtail] = 0;
00204 client_accept_input(client);
00205 dprintk("Would Parse: %s", client->inputbuffer);
00206 client->inputtail = 0;
00207 ring_eat(client, 1);
00208 break;
00209 default:
00210 client->inputbuffer[client->inputtail++] = ring_char(client, 0);
00211 ring_eat(client, 1);
00212 break;
00213 }
00214 }
00215 if(client->ringhead == client->ringtail) {
00216 client->ringhead = client->ringtail = 0;
00217 }
00218
00219 telnet_check_options(client);
00220 dprintk
00221 ("Ring Read finished. RingState = { head = %d, tail = %d }, InputState = { tail = %d }",
00222 client->ringhead, client->ringtail, client->inputtail);
00223 }
00224
00225 void telnet_disconnect(DESC * client)
00226 {
00227 network_disconnect(client);
00228 }
00229
00230 void telnet_write(DESC * client, char *buffer, int length)
00231 {
00232 dprintk("telnet_write");
00233
00234 network_write(client, buffer, length);
00235 }