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