00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "uip.h"
00036 #include "telnetd.h"
00037 #include "memb.h"
00038 #include "shell.h"
00039
00040 #include <string.h>
00041
00042 #define ISO_nl 0x0a
00043 #define ISO_cr 0x0d
00044
00045 struct telnetd_line {
00046 char line[TELNETD_CONF_LINELEN];
00047 };
00048 MEMB(linemem, struct telnetd_line, TELNETD_CONF_NUMLINES);
00049
00050 #define STATE_NORMAL 0
00051 #define STATE_IAC 1
00052 #define STATE_WILL 2
00053 #define STATE_WONT 3
00054 #define STATE_DO 4
00055 #define STATE_DONT 5
00056 #define STATE_CLOSE 6
00057
00058 static struct telnetd_state s;
00059
00060 #define TELNET_IAC 255
00061 #define TELNET_WILL 251
00062 #define TELNET_WONT 252
00063 #define TELNET_DO 253
00064 #define TELNET_DONT 254
00065
00066 static char *
00067 alloc_line(void)
00068 {
00069 return memb_alloc(&linemem);
00070 }
00071
00072 static void
00073 dealloc_line(char *line)
00074 {
00075 memb_free(&linemem, line);
00076 }
00077
00078 void
00079 shell_quit(char *str)
00080 {
00081 s.state = STATE_CLOSE;
00082 }
00083
00084 static void
00085 sendline(char *line)
00086 {
00087 static unsigned int i;
00088
00089 for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
00090 if(s.lines[i] == NULL) {
00091 s.lines[i] = line;
00092 break;
00093 }
00094 }
00095 if(i == TELNETD_CONF_NUMLINES) {
00096 dealloc_line(line);
00097 }
00098 }
00099
00100 void
00101 shell_prompt(char *str)
00102 {
00103 char *line;
00104 line = alloc_line();
00105 if(line != NULL) {
00106 strncpy(line, str, TELNETD_CONF_LINELEN);
00107
00108 sendline(line);
00109 }
00110 }
00111
00112 void
00113 shell_output(char *str1, char *str2)
00114 {
00115 static unsigned len;
00116 char *line;
00117
00118 line = alloc_line();
00119 if(line != NULL) {
00120 len = strlen(str1);
00121 strncpy(line, str1, TELNETD_CONF_LINELEN);
00122 if(len < TELNETD_CONF_LINELEN) {
00123 strncpy(line + len, str2, TELNETD_CONF_LINELEN - len);
00124 }
00125 len = strlen(line);
00126 if(len < TELNETD_CONF_LINELEN - 2) {
00127 line[len] = ISO_cr;
00128 line[len+1] = ISO_nl;
00129 line[len+2] = 0;
00130 }
00131
00132 sendline(line);
00133 }
00134 }
00135
00136 void
00137 telnetd_init(void)
00138 {
00139 uip_listen(HTONS(23));
00140 memb_init(&linemem);
00141 shell_init();
00142 }
00143
00144 static void
00145 acked(void)
00146 {
00147 static unsigned int i;
00148
00149 while(s.numsent > 0) {
00150 dealloc_line(s.lines[0]);
00151 for(i = 1; i < TELNETD_CONF_NUMLINES; ++i) {
00152 s.lines[i - 1] = s.lines[i];
00153 }
00154 s.lines[TELNETD_CONF_NUMLINES - 1] = NULL;
00155 --s.numsent;
00156 }
00157 }
00158
00159 static void
00160 senddata(void)
00161 {
00162 static char *bufptr, *lineptr;
00163 static int buflen, linelen;
00164
00165 bufptr = uip_appdata;
00166 buflen = 0;
00167 for(s.numsent = 0; s.numsent < TELNETD_CONF_NUMLINES &&
00168 s.lines[s.numsent] != NULL ; ++s.numsent) {
00169 lineptr = s.lines[s.numsent];
00170 linelen = strlen(lineptr);
00171 if(linelen > TELNETD_CONF_LINELEN) {
00172 linelen = TELNETD_CONF_LINELEN;
00173 }
00174 if(buflen + linelen < uip_mss()) {
00175 memcpy(bufptr, lineptr, linelen);
00176 bufptr += linelen;
00177 buflen += linelen;
00178 } else {
00179 break;
00180 }
00181 }
00182 uip_send(uip_appdata, buflen);
00183 }
00184
00185 static void
00186 closed(void)
00187 {
00188 static unsigned int i;
00189
00190 for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
00191 if(s.lines[i] != NULL) {
00192 dealloc_line(s.lines[i]);
00193 }
00194 }
00195 }
00196
00197 static void
00198 get_char(u8_t c)
00199 {
00200 if(c == ISO_cr) {
00201 return;
00202 }
00203
00204 s.buf[(int)s.bufptr] = c;
00205 if(s.buf[(int)s.bufptr] == ISO_nl ||
00206 s.bufptr == sizeof(s.buf) - 1) {
00207 if(s.bufptr > 0) {
00208 s.buf[(int)s.bufptr] = 0;
00209
00210 }
00211 shell_input(s.buf);
00212 s.bufptr = 0;
00213 } else {
00214 ++s.bufptr;
00215 }
00216 }
00217
00218 static void
00219 sendopt(u8_t option, u8_t value)
00220 {
00221 char *line;
00222 line = alloc_line();
00223 if(line != NULL) {
00224 line[0] = TELNET_IAC;
00225 line[1] = option;
00226 line[2] = value;
00227 line[3] = 0;
00228 sendline(line);
00229 }
00230 }
00231
00232 static void
00233 newdata(void)
00234 {
00235 u16_t len;
00236 u8_t c;
00237 char *dataptr;
00238
00239
00240 len = uip_datalen();
00241 dataptr = (char *)uip_appdata;
00242
00243 while(len > 0 && s.bufptr < sizeof(s.buf)) {
00244 c = *dataptr;
00245 ++dataptr;
00246 --len;
00247 switch(s.state) {
00248 case STATE_IAC:
00249 if(c == TELNET_IAC) {
00250 get_char(c);
00251 s.state = STATE_NORMAL;
00252 } else {
00253 switch(c) {
00254 case TELNET_WILL:
00255 s.state = STATE_WILL;
00256 break;
00257 case TELNET_WONT:
00258 s.state = STATE_WONT;
00259 break;
00260 case TELNET_DO:
00261 s.state = STATE_DO;
00262 break;
00263 case TELNET_DONT:
00264 s.state = STATE_DONT;
00265 break;
00266 default:
00267 s.state = STATE_NORMAL;
00268 break;
00269 }
00270 }
00271 break;
00272 case STATE_WILL:
00273
00274 sendopt(TELNET_DONT, c);
00275 s.state = STATE_NORMAL;
00276 break;
00277
00278 case STATE_WONT:
00279
00280 sendopt(TELNET_DONT, c);
00281 s.state = STATE_NORMAL;
00282 break;
00283 case STATE_DO:
00284
00285 sendopt(TELNET_WONT, c);
00286 s.state = STATE_NORMAL;
00287 break;
00288 case STATE_DONT:
00289
00290 sendopt(TELNET_WONT, c);
00291 s.state = STATE_NORMAL;
00292 break;
00293 case STATE_NORMAL:
00294 if(c == TELNET_IAC) {
00295 s.state = STATE_IAC;
00296 } else {
00297 get_char(c);
00298 }
00299 break;
00300 }
00301
00302
00303 }
00304
00305 }
00306
00307 void
00308 telnetd_appcall(void)
00309 {
00310 static unsigned int i;
00311 if(uip_connected()) {
00312
00313 for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
00314 s.lines[i] = NULL;
00315 }
00316 s.bufptr = 0;
00317 s.state = STATE_NORMAL;
00318
00319 shell_start();
00320 }
00321
00322 if(s.state == STATE_CLOSE) {
00323 s.state = STATE_NORMAL;
00324 uip_close();
00325 return;
00326 }
00327
00328 if(uip_closed() ||
00329 uip_aborted() ||
00330 uip_timedout()) {
00331 closed();
00332 }
00333
00334 if(uip_acked()) {
00335 acked();
00336 }
00337
00338 if(uip_newdata()) {
00339 newdata();
00340 }
00341
00342 if(uip_rexmit() ||
00343 uip_newdata() ||
00344 uip_acked() ||
00345 uip_connected() ||
00346 uip_poll()) {
00347 senddata();
00348 }
00349 }
00350