xref: /nrf52832-nimble/rt-thread/components/net/uip/apps/telnetd/telnetd.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2003, Adam Dunkels.
3*10465441SEvalZero  * All rights reserved.
4*10465441SEvalZero  *
5*10465441SEvalZero  * Redistribution and use in source and binary forms, with or without
6*10465441SEvalZero  * modification, are permitted provided that the following conditions
7*10465441SEvalZero  * are met:
8*10465441SEvalZero  * 1. Redistributions of source code must retain the above copyright
9*10465441SEvalZero  *    notice, this list of conditions and the following disclaimer.
10*10465441SEvalZero  * 2. Redistributions in binary form must reproduce the above copyright
11*10465441SEvalZero  *    notice, this list of conditions and the following disclaimer in the
12*10465441SEvalZero  *    documentation and/or other materials provided with the distribution.
13*10465441SEvalZero  * 3. The name of the author may not be used to endorse or promote
14*10465441SEvalZero  *    products derived from this software without specific prior
15*10465441SEvalZero  *    written permission.
16*10465441SEvalZero  *
17*10465441SEvalZero  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18*10465441SEvalZero  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19*10465441SEvalZero  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*10465441SEvalZero  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21*10465441SEvalZero  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*10465441SEvalZero  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*10465441SEvalZero  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*10465441SEvalZero  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25*10465441SEvalZero  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26*10465441SEvalZero  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27*10465441SEvalZero  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*10465441SEvalZero  *
29*10465441SEvalZero  * This file is part of the uIP TCP/IP stack
30*10465441SEvalZero  *
31*10465441SEvalZero  * $Id: telnetd.c,v 1.2 2006/06/07 09:43:54 adam Exp $
32*10465441SEvalZero  *
33*10465441SEvalZero  */
34*10465441SEvalZero 
35*10465441SEvalZero #include "uip.h"
36*10465441SEvalZero #include "telnetd.h"
37*10465441SEvalZero #include "memb.h"
38*10465441SEvalZero #include "shell.h"
39*10465441SEvalZero 
40*10465441SEvalZero #include <string.h>
41*10465441SEvalZero 
42*10465441SEvalZero #define ISO_nl       0x0a
43*10465441SEvalZero #define ISO_cr       0x0d
44*10465441SEvalZero 
45*10465441SEvalZero struct telnetd_line {
46*10465441SEvalZero   char line[TELNETD_CONF_LINELEN];
47*10465441SEvalZero };
48*10465441SEvalZero MEMB(linemem, struct telnetd_line, TELNETD_CONF_NUMLINES);
49*10465441SEvalZero 
50*10465441SEvalZero #define STATE_NORMAL 0
51*10465441SEvalZero #define STATE_IAC    1
52*10465441SEvalZero #define STATE_WILL   2
53*10465441SEvalZero #define STATE_WONT   3
54*10465441SEvalZero #define STATE_DO     4
55*10465441SEvalZero #define STATE_DONT   5
56*10465441SEvalZero #define STATE_CLOSE  6
57*10465441SEvalZero 
58*10465441SEvalZero static struct telnetd_state s;
59*10465441SEvalZero 
60*10465441SEvalZero #define TELNET_IAC   255
61*10465441SEvalZero #define TELNET_WILL  251
62*10465441SEvalZero #define TELNET_WONT  252
63*10465441SEvalZero #define TELNET_DO    253
64*10465441SEvalZero #define TELNET_DONT  254
65*10465441SEvalZero /*---------------------------------------------------------------------------*/
66*10465441SEvalZero static char *
alloc_line(void)67*10465441SEvalZero alloc_line(void)
68*10465441SEvalZero {
69*10465441SEvalZero   return memb_alloc(&linemem);
70*10465441SEvalZero }
71*10465441SEvalZero /*---------------------------------------------------------------------------*/
72*10465441SEvalZero static void
dealloc_line(char * line)73*10465441SEvalZero dealloc_line(char *line)
74*10465441SEvalZero {
75*10465441SEvalZero   memb_free(&linemem, line);
76*10465441SEvalZero }
77*10465441SEvalZero /*---------------------------------------------------------------------------*/
78*10465441SEvalZero void
shell_quit(char * str)79*10465441SEvalZero shell_quit(char *str)
80*10465441SEvalZero {
81*10465441SEvalZero   s.state = STATE_CLOSE;
82*10465441SEvalZero }
83*10465441SEvalZero /*---------------------------------------------------------------------------*/
84*10465441SEvalZero static void
sendline(char * line)85*10465441SEvalZero sendline(char *line)
86*10465441SEvalZero {
87*10465441SEvalZero   static unsigned int i;
88*10465441SEvalZero 
89*10465441SEvalZero   for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
90*10465441SEvalZero     if(s.lines[i] == NULL) {
91*10465441SEvalZero       s.lines[i] = line;
92*10465441SEvalZero       break;
93*10465441SEvalZero     }
94*10465441SEvalZero   }
95*10465441SEvalZero   if(i == TELNETD_CONF_NUMLINES) {
96*10465441SEvalZero     dealloc_line(line);
97*10465441SEvalZero   }
98*10465441SEvalZero }
99*10465441SEvalZero /*---------------------------------------------------------------------------*/
100*10465441SEvalZero void
shell_prompt(char * str)101*10465441SEvalZero shell_prompt(char *str)
102*10465441SEvalZero {
103*10465441SEvalZero   char *line;
104*10465441SEvalZero   line = alloc_line();
105*10465441SEvalZero   if(line != NULL) {
106*10465441SEvalZero     strncpy(line, str, TELNETD_CONF_LINELEN);
107*10465441SEvalZero     /*    petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
108*10465441SEvalZero     sendline(line);
109*10465441SEvalZero   }
110*10465441SEvalZero }
111*10465441SEvalZero /*---------------------------------------------------------------------------*/
112*10465441SEvalZero void
shell_output(char * str1,char * str2)113*10465441SEvalZero shell_output(char *str1, char *str2)
114*10465441SEvalZero {
115*10465441SEvalZero   static unsigned len;
116*10465441SEvalZero   char *line;
117*10465441SEvalZero 
118*10465441SEvalZero   line = alloc_line();
119*10465441SEvalZero   if(line != NULL) {
120*10465441SEvalZero     len = strlen(str1);
121*10465441SEvalZero     strncpy(line, str1, TELNETD_CONF_LINELEN);
122*10465441SEvalZero     if(len < TELNETD_CONF_LINELEN) {
123*10465441SEvalZero       strncpy(line + len, str2, TELNETD_CONF_LINELEN - len);
124*10465441SEvalZero     }
125*10465441SEvalZero     len = strlen(line);
126*10465441SEvalZero     if(len < TELNETD_CONF_LINELEN - 2) {
127*10465441SEvalZero       line[len] = ISO_cr;
128*10465441SEvalZero       line[len+1] = ISO_nl;
129*10465441SEvalZero       line[len+2] = 0;
130*10465441SEvalZero     }
131*10465441SEvalZero     /*    petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
132*10465441SEvalZero     sendline(line);
133*10465441SEvalZero   }
134*10465441SEvalZero }
135*10465441SEvalZero /*---------------------------------------------------------------------------*/
136*10465441SEvalZero void
telnetd_init(void)137*10465441SEvalZero telnetd_init(void)
138*10465441SEvalZero {
139*10465441SEvalZero   uip_listen(HTONS(23));
140*10465441SEvalZero   memb_init(&linemem);
141*10465441SEvalZero   shell_init();
142*10465441SEvalZero }
143*10465441SEvalZero /*---------------------------------------------------------------------------*/
144*10465441SEvalZero static void
acked(void)145*10465441SEvalZero acked(void)
146*10465441SEvalZero {
147*10465441SEvalZero   static unsigned int i;
148*10465441SEvalZero 
149*10465441SEvalZero   while(s.numsent > 0) {
150*10465441SEvalZero     dealloc_line(s.lines[0]);
151*10465441SEvalZero     for(i = 1; i < TELNETD_CONF_NUMLINES; ++i) {
152*10465441SEvalZero       s.lines[i - 1] = s.lines[i];
153*10465441SEvalZero     }
154*10465441SEvalZero     s.lines[TELNETD_CONF_NUMLINES - 1] = NULL;
155*10465441SEvalZero     --s.numsent;
156*10465441SEvalZero   }
157*10465441SEvalZero }
158*10465441SEvalZero /*---------------------------------------------------------------------------*/
159*10465441SEvalZero static void
senddata(void)160*10465441SEvalZero senddata(void)
161*10465441SEvalZero {
162*10465441SEvalZero   static char *bufptr, *lineptr;
163*10465441SEvalZero   static int buflen, linelen;
164*10465441SEvalZero 
165*10465441SEvalZero   bufptr = uip_appdata;
166*10465441SEvalZero   buflen = 0;
167*10465441SEvalZero   for(s.numsent = 0; s.numsent < TELNETD_CONF_NUMLINES &&
168*10465441SEvalZero 	s.lines[s.numsent] != NULL ; ++s.numsent) {
169*10465441SEvalZero     lineptr = s.lines[s.numsent];
170*10465441SEvalZero     linelen = strlen(lineptr);
171*10465441SEvalZero     if(linelen > TELNETD_CONF_LINELEN) {
172*10465441SEvalZero       linelen = TELNETD_CONF_LINELEN;
173*10465441SEvalZero     }
174*10465441SEvalZero     if(buflen + linelen < uip_mss()) {
175*10465441SEvalZero       memcpy(bufptr, lineptr, linelen);
176*10465441SEvalZero       bufptr += linelen;
177*10465441SEvalZero       buflen += linelen;
178*10465441SEvalZero     } else {
179*10465441SEvalZero       break;
180*10465441SEvalZero     }
181*10465441SEvalZero   }
182*10465441SEvalZero   uip_send(uip_appdata, buflen);
183*10465441SEvalZero }
184*10465441SEvalZero /*---------------------------------------------------------------------------*/
185*10465441SEvalZero static void
closed(void)186*10465441SEvalZero closed(void)
187*10465441SEvalZero {
188*10465441SEvalZero   static unsigned int i;
189*10465441SEvalZero 
190*10465441SEvalZero   for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
191*10465441SEvalZero     if(s.lines[i] != NULL) {
192*10465441SEvalZero       dealloc_line(s.lines[i]);
193*10465441SEvalZero     }
194*10465441SEvalZero   }
195*10465441SEvalZero }
196*10465441SEvalZero /*---------------------------------------------------------------------------*/
197*10465441SEvalZero static void
get_char(u8_t c)198*10465441SEvalZero get_char(u8_t c)
199*10465441SEvalZero {
200*10465441SEvalZero   if(c == ISO_cr) {
201*10465441SEvalZero     return;
202*10465441SEvalZero   }
203*10465441SEvalZero 
204*10465441SEvalZero   s.buf[(int)s.bufptr] = c;
205*10465441SEvalZero   if(s.buf[(int)s.bufptr] == ISO_nl ||
206*10465441SEvalZero      s.bufptr == sizeof(s.buf) - 1) {
207*10465441SEvalZero     if(s.bufptr > 0) {
208*10465441SEvalZero       s.buf[(int)s.bufptr] = 0;
209*10465441SEvalZero       /*      petsciiconv_topetscii(s.buf, TELNETD_CONF_LINELEN);*/
210*10465441SEvalZero     }
211*10465441SEvalZero     shell_input(s.buf);
212*10465441SEvalZero     s.bufptr = 0;
213*10465441SEvalZero   } else {
214*10465441SEvalZero     ++s.bufptr;
215*10465441SEvalZero   }
216*10465441SEvalZero }
217*10465441SEvalZero /*---------------------------------------------------------------------------*/
218*10465441SEvalZero static void
sendopt(u8_t option,u8_t value)219*10465441SEvalZero sendopt(u8_t option, u8_t value)
220*10465441SEvalZero {
221*10465441SEvalZero   char *line;
222*10465441SEvalZero   line = alloc_line();
223*10465441SEvalZero   if(line != NULL) {
224*10465441SEvalZero     line[0] = TELNET_IAC;
225*10465441SEvalZero     line[1] = option;
226*10465441SEvalZero     line[2] = value;
227*10465441SEvalZero     line[3] = 0;
228*10465441SEvalZero     sendline(line);
229*10465441SEvalZero   }
230*10465441SEvalZero }
231*10465441SEvalZero /*---------------------------------------------------------------------------*/
232*10465441SEvalZero static void
newdata(void)233*10465441SEvalZero newdata(void)
234*10465441SEvalZero {
235*10465441SEvalZero   u16_t len;
236*10465441SEvalZero   u8_t c;
237*10465441SEvalZero   char *dataptr;
238*10465441SEvalZero 
239*10465441SEvalZero 
240*10465441SEvalZero   len = uip_datalen();
241*10465441SEvalZero   dataptr = (char *)uip_appdata;
242*10465441SEvalZero 
243*10465441SEvalZero   while(len > 0 && s.bufptr < sizeof(s.buf)) {
244*10465441SEvalZero     c = *dataptr;
245*10465441SEvalZero     ++dataptr;
246*10465441SEvalZero     --len;
247*10465441SEvalZero     switch(s.state) {
248*10465441SEvalZero     case STATE_IAC:
249*10465441SEvalZero       if(c == TELNET_IAC) {
250*10465441SEvalZero 	get_char(c);
251*10465441SEvalZero 	s.state = STATE_NORMAL;
252*10465441SEvalZero       } else {
253*10465441SEvalZero 	switch(c) {
254*10465441SEvalZero 	case TELNET_WILL:
255*10465441SEvalZero 	  s.state = STATE_WILL;
256*10465441SEvalZero 	  break;
257*10465441SEvalZero 	case TELNET_WONT:
258*10465441SEvalZero 	  s.state = STATE_WONT;
259*10465441SEvalZero 	  break;
260*10465441SEvalZero 	case TELNET_DO:
261*10465441SEvalZero 	  s.state = STATE_DO;
262*10465441SEvalZero 	  break;
263*10465441SEvalZero 	case TELNET_DONT:
264*10465441SEvalZero 	  s.state = STATE_DONT;
265*10465441SEvalZero 	  break;
266*10465441SEvalZero 	default:
267*10465441SEvalZero 	  s.state = STATE_NORMAL;
268*10465441SEvalZero 	  break;
269*10465441SEvalZero 	}
270*10465441SEvalZero       }
271*10465441SEvalZero       break;
272*10465441SEvalZero     case STATE_WILL:
273*10465441SEvalZero       /* Reply with a DONT */
274*10465441SEvalZero       sendopt(TELNET_DONT, c);
275*10465441SEvalZero       s.state = STATE_NORMAL;
276*10465441SEvalZero       break;
277*10465441SEvalZero 
278*10465441SEvalZero     case STATE_WONT:
279*10465441SEvalZero       /* Reply with a DONT */
280*10465441SEvalZero       sendopt(TELNET_DONT, c);
281*10465441SEvalZero       s.state = STATE_NORMAL;
282*10465441SEvalZero       break;
283*10465441SEvalZero     case STATE_DO:
284*10465441SEvalZero       /* Reply with a WONT */
285*10465441SEvalZero       sendopt(TELNET_WONT, c);
286*10465441SEvalZero       s.state = STATE_NORMAL;
287*10465441SEvalZero       break;
288*10465441SEvalZero     case STATE_DONT:
289*10465441SEvalZero       /* Reply with a WONT */
290*10465441SEvalZero       sendopt(TELNET_WONT, c);
291*10465441SEvalZero       s.state = STATE_NORMAL;
292*10465441SEvalZero       break;
293*10465441SEvalZero     case STATE_NORMAL:
294*10465441SEvalZero       if(c == TELNET_IAC) {
295*10465441SEvalZero 	s.state = STATE_IAC;
296*10465441SEvalZero       } else {
297*10465441SEvalZero 	get_char(c);
298*10465441SEvalZero       }
299*10465441SEvalZero       break;
300*10465441SEvalZero     }
301*10465441SEvalZero 
302*10465441SEvalZero 
303*10465441SEvalZero   }
304*10465441SEvalZero 
305*10465441SEvalZero }
306*10465441SEvalZero /*---------------------------------------------------------------------------*/
307*10465441SEvalZero void
telnetd_appcall(void)308*10465441SEvalZero telnetd_appcall(void)
309*10465441SEvalZero {
310*10465441SEvalZero   static unsigned int i;
311*10465441SEvalZero   if(uip_connected()) {
312*10465441SEvalZero     /*    tcp_markconn(uip_conn, &s);*/
313*10465441SEvalZero     for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
314*10465441SEvalZero       s.lines[i] = NULL;
315*10465441SEvalZero     }
316*10465441SEvalZero     s.bufptr = 0;
317*10465441SEvalZero     s.state = STATE_NORMAL;
318*10465441SEvalZero 
319*10465441SEvalZero     shell_start();
320*10465441SEvalZero   }
321*10465441SEvalZero 
322*10465441SEvalZero   if(s.state == STATE_CLOSE) {
323*10465441SEvalZero     s.state = STATE_NORMAL;
324*10465441SEvalZero     uip_close();
325*10465441SEvalZero     return;
326*10465441SEvalZero   }
327*10465441SEvalZero 
328*10465441SEvalZero   if(uip_closed() ||
329*10465441SEvalZero      uip_aborted() ||
330*10465441SEvalZero      uip_timedout()) {
331*10465441SEvalZero     closed();
332*10465441SEvalZero   }
333*10465441SEvalZero 
334*10465441SEvalZero   if(uip_acked()) {
335*10465441SEvalZero     acked();
336*10465441SEvalZero   }
337*10465441SEvalZero 
338*10465441SEvalZero   if(uip_newdata()) {
339*10465441SEvalZero     newdata();
340*10465441SEvalZero   }
341*10465441SEvalZero 
342*10465441SEvalZero   if(uip_rexmit() ||
343*10465441SEvalZero      uip_newdata() ||
344*10465441SEvalZero      uip_acked() ||
345*10465441SEvalZero      uip_connected() ||
346*10465441SEvalZero      uip_poll()) {
347*10465441SEvalZero     senddata();
348*10465441SEvalZero   }
349*10465441SEvalZero }
350*10465441SEvalZero /*---------------------------------------------------------------------------*/
351