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