• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  *
29  * Author: Adam Dunkels <adam@sics.se>
30  *
31  */
32 
33 #include "shell.h"
34 
35 #include "lwip/opt.h"
36 
37 #if LWIP_NETCONN && LWIP_TCP
38 
39 #include <string.h>
40 #include <stdio.h>
41 
42 #include "lwip/mem.h"
43 #include "lwip/debug.h"
44 #include "lwip/def.h"
45 #include "lwip/api.h"
46 #include "lwip/stats.h"
47 
48 #if LWIP_SOCKET
49 #include "lwip/errno.h"
50 #include "lwip/if_api.h"
51 #endif
52 
53 #ifdef WIN32
54 #define NEWLINE "\r\n"
55 #else /* WIN32 */
56 #define NEWLINE "\n"
57 #endif /* WIN32 */
58 
59 /** Define this to 1 if you want to echo back all received characters
60  * (e.g. so they are displayed on a remote telnet)
61  */
62 #ifndef SHELL_ECHO
63 #define SHELL_ECHO 0
64 #endif
65 
66 #define BUFSIZE             1024
67 static unsigned char buffer[BUFSIZE];
68 
69 struct command {
70   struct netconn *conn;
71   s8_t (* exec)(struct command *);
72   u8_t nargs;
73   char *args[10];
74 };
75 
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <limits.h>
79 
80 #define ESUCCESS 0
81 #define ESYNTAX -1
82 #define ETOOFEW -2
83 #define ETOOMANY -3
84 #define ECLOSED -4
85 
86 #define NCONNS 10
87 static struct netconn *conns[NCONNS];
88 
89 /* help_msg is split into 3 strings to prevent exceeding the C89 maximum length of 509 per string */
90 static char help_msg1[] = "Available commands:"NEWLINE"\
91 open [IP address] [TCP port]: opens a TCP connection to the specified address."NEWLINE"\
92 lstn [TCP port]: sets up a server on the specified port."NEWLINE"\
93 acpt [connection #]: waits for an incoming connection request."NEWLINE"\
94 send [connection #] [message]: sends a message on a TCP connection."NEWLINE"\
95 udpc [local UDP port] [IP address] [remote port]: opens a UDP \"connection\"."NEWLINE"\
96 udpl [local UDP port] [IP address] [remote port]: opens a UDP-Lite \"connection\"."NEWLINE"";
97 static char help_msg2[] = "udpn [local UDP port] [IP address] [remote port]: opens a UDP \"connection\" without checksums."NEWLINE"\
98 udpb [local port] [remote port]: opens a UDP broadcast \"connection\"."NEWLINE"\
99 usnd [connection #] [message]: sends a message on a UDP connection."NEWLINE"\
100 recv [connection #]: receives data on a TCP or UDP connection."NEWLINE"\
101 clos [connection #]: closes a TCP or UDP connection."NEWLINE"\
102 stat: prints out lwIP statistics."NEWLINE"\
103 idxtoname [index]: outputs interface name from index."NEWLINE"\
104 nametoidx [name]: outputs interface index from name."NEWLINE;
105 static char help_msg3[] =
106 "gethostnm [name]: outputs IP address of host."NEWLINE"\
107 quit: quits"NEWLINE"";
108 
109 #if LWIP_STATS
110 static char padding_10spaces[] = "          ";
111 
112 #define PROTOCOL_STATS (LINK_STATS && ETHARP_STATS && IPFRAG_STATS && IP_STATS && ICMP_STATS && UDP_STATS && TCP_STATS)
113 
114 #if PROTOCOL_STATS
115 static const char* shell_stat_proto_names[] = {
116 #if LINK_STATS
117   "LINK      ",
118 #endif
119 #if ETHARP_STATS
120   "ETHARP    ",
121 #endif
122 #if IPFRAG_STATS
123   "IP_FRAG   ",
124 #endif
125 #if IP_STATS
126   "IP        ",
127 #endif
128 #if ICMP_STATS
129   "ICMP      ",
130 #endif
131 #if UDP_STATS
132   "UDP       ",
133 #endif
134 #if TCP_STATS
135   "TCP       ",
136 #endif
137   "last"
138 };
139 
140 static struct stats_proto* shell_stat_proto_stats[] = {
141 #if LINK_STATS
142   &lwip_stats.link,
143 #endif
144 #if ETHARP_STATS
145   &lwip_stats.etharp,
146 #endif
147 #if IPFRAG_STATS
148   &lwip_stats.ip_frag,
149 #endif
150 #if IP_STATS
151   &lwip_stats.ip,
152 #endif
153 #if ICMP_STATS
154   &lwip_stats.icmp,
155 #endif
156 #if UDP_STATS
157   &lwip_stats.udp,
158 #endif
159 #if TCP_STATS
160   &lwip_stats.tcp,
161 #endif
162 };
163 static const size_t num_protostats = sizeof(shell_stat_proto_stats)/sizeof(struct stats_proto*);
164 
165 static const char *stat_msgs_proto[] = {
166   " * transmitted ",
167   "           * received ",
168   "             forwarded ",
169   "           * dropped ",
170   "           * checksum errors ",
171   "           * length errors ",
172   "           * memory errors ",
173   "             routing errors ",
174   "             protocol errors ",
175   "             option errors ",
176   "           * misc errors ",
177   "             cache hits "
178 };
179 #endif /* PROTOCOL_STATS */
180 #endif /* LWIP_STATS */
181 
182 /*-----------------------------------------------------------------------------------*/
183 static void
sendstr(const char * str,struct netconn * conn)184 sendstr(const char *str, struct netconn *conn)
185 {
186   netconn_write(conn, (const void *)str, strlen(str), NETCONN_NOCOPY);
187 }
188 /*-----------------------------------------------------------------------------------*/
189 static s8_t
com_open(struct command * com)190 com_open(struct command *com)
191 {
192   ip_addr_t ipaddr;
193   u16_t port;
194   int i;
195   err_t err;
196   long tmp;
197 
198   if (ipaddr_aton(com->args[0], &ipaddr) == -1) {
199     sendstr(strerror(errno), com->conn);
200     return ESYNTAX;
201   }
202   tmp = strtol(com->args[1], NULL, 10);
203   if((tmp < 0) || (tmp > 0xffff)) {
204     sendstr("Invalid port number."NEWLINE, com->conn);
205     return ESUCCESS;
206   }
207   port = (u16_t)tmp;
208 
209   /* Find the first unused connection in conns. */
210   for(i = 0; i < NCONNS && conns[i] != NULL; i++);
211 
212   if (i == NCONNS) {
213     sendstr("No more connections available, sorry."NEWLINE, com->conn);
214     return ESUCCESS;
215   }
216 
217   sendstr("Opening connection to ", com->conn);
218   netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
219   sendstr(":", com->conn);
220   netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
221   sendstr(NEWLINE, com->conn);
222 
223   conns[i] = netconn_new(NETCONN_TCP);
224   if (conns[i] == NULL) {
225     sendstr("Could not create connection identifier (out of memory)."NEWLINE, com->conn);
226     return ESUCCESS;
227   }
228   err = netconn_connect(conns[i], &ipaddr, port);
229   if (err != ERR_OK) {
230     fprintf(stderr, "error %s"NEWLINE, lwip_strerr(err));
231     sendstr("Could not connect to remote host: ", com->conn);
232 #ifdef LWIP_DEBUG
233     sendstr(lwip_strerr(err), com->conn);
234 #else
235     sendstr("(debugging must be turned on for error message to appear)", com->conn);
236 #endif /* LWIP_DEBUG */
237     sendstr(NEWLINE, com->conn);
238     netconn_delete(conns[i]);
239     conns[i] = NULL;
240     return ESUCCESS;
241   }
242 
243   sendstr("Opened connection, connection identifier is ", com->conn);
244   snprintf((char *)buffer, sizeof(buffer), "%d"NEWLINE, i);
245   netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
246 
247   return ESUCCESS;
248 }
249 /*-----------------------------------------------------------------------------------*/
250 static s8_t
com_lstn(struct command * com)251 com_lstn(struct command *com)
252 {
253   u16_t port;
254   int i;
255   err_t err;
256   long tmp;
257 
258   tmp = strtol(com->args[0], NULL, 10);
259   if((tmp < 0) || (tmp > 0xffff)) {
260     sendstr("Invalid port number."NEWLINE, com->conn);
261     return ESUCCESS;
262   }
263   port = (u16_t)tmp;
264 
265   /* Find the first unused connection in conns. */
266   for(i = 0; i < NCONNS && conns[i] != NULL; i++);
267 
268   if (i == NCONNS) {
269     sendstr("No more connections available, sorry."NEWLINE, com->conn);
270     return ESUCCESS;
271   }
272 
273   sendstr("Opening a listening connection on port ", com->conn);
274   netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
275   sendstr(NEWLINE, com->conn);
276 
277   conns[i] = netconn_new(NETCONN_TCP);
278   if (conns[i] == NULL) {
279     sendstr("Could not create connection identifier (out of memory)."NEWLINE, com->conn);
280     return ESUCCESS;
281   }
282 
283   err = netconn_bind(conns[i], IP_ADDR_ANY, port);
284   if (err != ERR_OK) {
285     netconn_delete(conns[i]);
286     conns[i] = NULL;
287     sendstr("Could not bind: ", com->conn);
288 #ifdef LWIP_DEBUG
289     sendstr(lwip_strerr(err), com->conn);
290 #else
291     sendstr("(debugging must be turned on for error message to appear)", com->conn);
292 #endif /* LWIP_DEBUG */
293     sendstr(NEWLINE, com->conn);
294     return ESUCCESS;
295   }
296 
297   err = netconn_listen(conns[i]);
298   if (err != ERR_OK) {
299     netconn_delete(conns[i]);
300     conns[i] = NULL;
301     sendstr("Could not listen: ", com->conn);
302 #ifdef LWIP_DEBUG
303     sendstr(lwip_strerr(err), com->conn);
304 #else
305     sendstr("(debugging must be turned on for error message to appear)", com->conn);
306 #endif /* LWIP_DEBUG */
307     sendstr(NEWLINE, com->conn);
308     return ESUCCESS;
309   }
310 
311   sendstr("Opened connection, connection identifier is ", com->conn);
312   snprintf((char *)buffer, sizeof(buffer), "%d"NEWLINE, i);
313   netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
314 
315   return ESUCCESS;
316 }
317 /*-----------------------------------------------------------------------------------*/
318 /*-----------------------------------------------------------------------------------*/
319 static s8_t
com_clos(struct command * com)320 com_clos(struct command *com)
321 {
322   int i;
323   err_t err;
324 
325   i = strtol(com->args[0], NULL, 10);
326 
327   if (i > NCONNS) {
328     sendstr("Connection identifier too high."NEWLINE, com->conn);
329     return ESUCCESS;
330   }
331   if (conns[i] == NULL) {
332     sendstr("Connection identifier not in use."NEWLINE, com->conn);
333     return ESUCCESS;
334   }
335 
336   err = netconn_close(conns[i]);
337   if (err != ERR_OK) {
338     sendstr("Could not close connection: ", com->conn);
339 #ifdef LWIP_DEBUG
340     sendstr(lwip_strerr(err), com->conn);
341 #else
342     sendstr("(debugging must be turned on for error message to appear)", com->conn);
343 #endif /* LWIP_DEBUG */
344     sendstr(NEWLINE, com->conn);
345     return ESUCCESS;
346   }
347 
348   sendstr("Connection closed."NEWLINE, com->conn);
349   netconn_delete(conns[i]);
350   conns[i] = NULL;
351   return ESUCCESS;
352 }
353 /*-----------------------------------------------------------------------------------*/
354 static s8_t
com_acpt(struct command * com)355 com_acpt(struct command *com)
356 {
357   int i, j;
358   err_t err;
359 
360   /* Find the first unused connection in conns. */
361   for(j = 0; j < NCONNS && conns[j] != NULL; j++);
362 
363   if (j == NCONNS) {
364     sendstr("No more connections available, sorry."NEWLINE, com->conn);
365     return ESUCCESS;
366   }
367 
368   i = strtol(com->args[0], NULL, 10);
369 
370   if (i > NCONNS) {
371     sendstr("Connection identifier too high."NEWLINE, com->conn);
372     return ESUCCESS;
373   }
374   if (conns[i] == NULL) {
375     sendstr("Connection identifier not in use."NEWLINE, com->conn);
376     return ESUCCESS;
377   }
378 
379   err = netconn_accept(conns[i], &conns[j]);
380 
381   if (err != ERR_OK) {
382     sendstr("Could not accept connection: ", com->conn);
383 #ifdef LWIP_DEBUG
384     sendstr(lwip_strerr(err), com->conn);
385 #else
386     sendstr("(debugging must be turned on for error message to appear)", com->conn);
387 #endif /* LWIP_DEBUG */
388     sendstr(NEWLINE, com->conn);
389     return ESUCCESS;
390   }
391 
392   sendstr("Accepted connection, connection identifier for new connection is ", com->conn);
393   snprintf((char *)buffer, sizeof(buffer), "%d"NEWLINE, j);
394   netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
395 
396   return ESUCCESS;
397 }
398 /*-----------------------------------------------------------------------------------*/
399 #if LWIP_STATS
400 static void
com_stat_write_mem(struct netconn * conn,struct stats_mem * elem,int i)401 com_stat_write_mem(struct netconn *conn, struct stats_mem *elem, int i)
402 {
403   u16_t len;
404   char buf[100];
405   size_t slen;
406 
407 #ifdef LWIP_DEBUG
408   LWIP_UNUSED_ARG(i);
409   slen = strlen(elem->name);
410   netconn_write(conn, elem->name, slen, NETCONN_COPY);
411 #else /*  LWIP_DEBUG */
412   len = (u16_t)sprintf(buf, "%d", i);
413   slen = strlen(buf);
414   netconn_write(conn, buf, slen, NETCONN_COPY);
415 #endif /*  LWIP_DEBUG */
416   if(slen < 10) {
417     netconn_write(conn, padding_10spaces, 10-slen, NETCONN_COPY);
418   }
419 
420   len = (u16_t)sprintf(buf, " * available %"MEM_SIZE_F NEWLINE, elem->avail);
421   netconn_write(conn, buf, len, NETCONN_COPY);
422   len = (u16_t)sprintf(buf, "           * used %"MEM_SIZE_F NEWLINE, elem->used);
423   netconn_write(conn, buf, len, NETCONN_COPY);
424   len = (u16_t)sprintf(buf, "           * high water mark %"MEM_SIZE_F NEWLINE, elem->max);
425   netconn_write(conn, buf, len, NETCONN_COPY);
426   len = (u16_t)sprintf(buf, "           * errors %"STAT_COUNTER_F NEWLINE, elem->err);
427   netconn_write(conn, buf, len, NETCONN_COPY);
428   len = (u16_t)sprintf(buf, "           * illegal %"STAT_COUNTER_F NEWLINE, elem->illegal);
429   netconn_write(conn, buf, len, NETCONN_COPY);
430 }
431 static void
com_stat_write_sys(struct netconn * conn,struct stats_syselem * elem,const char * name)432 com_stat_write_sys(struct netconn *conn, struct stats_syselem *elem, const char *name)
433 {
434   u16_t len;
435   char buf[100];
436   size_t slen = strlen(name);
437 
438   netconn_write(conn, name, slen, NETCONN_COPY);
439   if(slen < 10) {
440     netconn_write(conn, padding_10spaces, 10-slen, NETCONN_COPY);
441   }
442 
443   len = (u16_t)sprintf(buf, " * used %"STAT_COUNTER_F NEWLINE, elem->used);
444   netconn_write(conn, buf, len, NETCONN_COPY);
445   len = (u16_t)sprintf(buf, "           * high water mark %"STAT_COUNTER_F NEWLINE, elem->max);
446   netconn_write(conn, buf, len, NETCONN_COPY);
447   len = (u16_t)sprintf(buf, "           * errors %"STAT_COUNTER_F NEWLINE, elem->err);
448   netconn_write(conn, buf, len, NETCONN_COPY);
449 }
450 static s8_t
com_stat(struct command * com)451 com_stat(struct command *com)
452 {
453 #if PROTOCOL_STATS || MEMP_STATS
454   size_t i;
455 #endif /* PROTOCOL_STATS || MEMP_STATS */
456 #if PROTOCOL_STATS
457   size_t k;
458   char buf[100];
459   u16_t len;
460 
461   /* protocol stats, @todo: add IGMP */
462   for(i = 0; i < num_protostats; i++) {
463     size_t s = sizeof(struct stats_proto)/sizeof(STAT_COUNTER);
464     STAT_COUNTER *c = &shell_stat_proto_stats[i]->xmit;
465     LWIP_ASSERT("stats not in sync", s == sizeof(stat_msgs_proto)/sizeof(char*));
466     netconn_write(com->conn, shell_stat_proto_names[i], strlen(shell_stat_proto_names[i]), NETCONN_COPY);
467     for(k = 0; k < s; k++) {
468       len = (u16_t)sprintf(buf, "%s%"STAT_COUNTER_F NEWLINE, stat_msgs_proto[k], c[k]);
469       netconn_write(com->conn, buf, len, NETCONN_COPY);
470     }
471   }
472 #endif /* PROTOCOL_STATS */
473 #if MEM_STATS
474   com_stat_write_mem(com->conn, &lwip_stats.mem, -1);
475 #endif /* MEM_STATS */
476 #if MEMP_STATS
477   for(i = 0; i < MEMP_MAX; i++) {
478     com_stat_write_mem(com->conn, lwip_stats.memp[i], -1);
479   }
480 #endif /* MEMP_STATS */
481 #if SYS_STATS
482   com_stat_write_sys(com->conn, &lwip_stats.sys.sem,   "SEM       ");
483   com_stat_write_sys(com->conn, &lwip_stats.sys.mutex, "MUTEX     ");
484   com_stat_write_sys(com->conn, &lwip_stats.sys.mbox,  "MBOX      ");
485 #endif /* SYS_STATS */
486 
487   return ESUCCESS;
488 }
489 #endif
490 /*-----------------------------------------------------------------------------------*/
491 static s8_t
com_send(struct command * com)492 com_send(struct command *com)
493 {
494   int i;
495   err_t err;
496   size_t len;
497 
498   i = strtol(com->args[0], NULL, 10);
499 
500   if (i > NCONNS) {
501     sendstr("Connection identifier too high."NEWLINE, com->conn);
502     return ESUCCESS;
503   }
504 
505   if (conns[i] == NULL) {
506     sendstr("Connection identifier not in use."NEWLINE, com->conn);
507     return ESUCCESS;
508   }
509 
510   len = strlen(com->args[1]);
511   com->args[1][len] = '\r';
512   com->args[1][len + 1] = '\n';
513   com->args[1][len + 2] = 0;
514 
515   err = netconn_write(conns[i], com->args[1], len + 3, NETCONN_COPY);
516   if (err != ERR_OK) {
517     sendstr("Could not send data: ", com->conn);
518 #ifdef LWIP_DEBUG
519     sendstr(lwip_strerr(err), com->conn);
520 #else
521     sendstr("(debugging must be turned on for error message to appear)", com->conn);
522 #endif /* LWIP_DEBUG */
523     sendstr(NEWLINE, com->conn);
524     return ESUCCESS;
525   }
526 
527   sendstr("Data enqueued for sending."NEWLINE, com->conn);
528   return ESUCCESS;
529 }
530 /*-----------------------------------------------------------------------------------*/
531 static s8_t
com_recv(struct command * com)532 com_recv(struct command *com)
533 {
534   int i;
535   err_t err;
536   struct netbuf *buf;
537   u16_t len;
538 
539   i = strtol(com->args[0], NULL, 10);
540 
541   if (i > NCONNS) {
542     sendstr("Connection identifier too high."NEWLINE, com->conn);
543     return ESUCCESS;
544   }
545 
546   if (conns[i] == NULL) {
547     sendstr("Connection identifier not in use."NEWLINE, com->conn);
548     return ESUCCESS;
549   }
550 
551   err = netconn_recv(conns[i], &buf);
552   if (err == ERR_OK) {
553 
554     netbuf_copy(buf, buffer, BUFSIZE);
555     len = netbuf_len(buf);
556     sendstr("Reading from connection:"NEWLINE, com->conn);
557     netconn_write(com->conn, buffer, len, NETCONN_COPY);
558     netbuf_delete(buf);
559   } else {
560     sendstr("EOF."NEWLINE, com->conn);
561   }
562   err = netconn_err(conns[i]);
563   if (err != ERR_OK) {
564     sendstr("Could not receive data: ", com->conn);
565 #ifdef LWIP_DEBUG
566     sendstr(lwip_strerr(err), com->conn);
567 #else
568     sendstr("(debugging must be turned on for error message to appear)", com->conn);
569 #endif /* LWIP_DEBUG */
570     sendstr(NEWLINE, com->conn);
571     return ESUCCESS;
572   }
573   return ESUCCESS;
574 }
575 /*-----------------------------------------------------------------------------------*/
576 static s8_t
com_udpc(struct command * com)577 com_udpc(struct command *com)
578 {
579   ip_addr_t ipaddr;
580   u16_t lport, rport;
581   int i;
582   err_t err;
583   long tmp;
584 
585   tmp = strtol(com->args[0], NULL, 10);
586   if((tmp < 0) || (tmp > 0xffff)) {
587     sendstr("Invalid port number."NEWLINE, com->conn);
588     return ESUCCESS;
589   }
590   lport = (u16_t)tmp;
591   if (ipaddr_aton(com->args[1], &ipaddr) == -1) {
592     sendstr(strerror(errno), com->conn);
593     return ESYNTAX;
594   }
595   tmp = strtol(com->args[2], NULL, 10);
596   if((tmp < 0) || (tmp > 0xffff)) {
597     sendstr("Invalid port number."NEWLINE, com->conn);
598     return ESUCCESS;
599   }
600   rport = (u16_t)tmp;
601 
602   /* Find the first unused connection in conns. */
603   for(i = 0; i < NCONNS && conns[i] != NULL; i++);
604 
605   if (i == NCONNS) {
606     sendstr("No more connections available, sorry."NEWLINE, com->conn);
607     return ESUCCESS;
608   }
609 
610   sendstr("Setting up UDP connection from port ", com->conn);
611   netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
612   sendstr(" to ", com->conn);
613   netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
614   sendstr(":", com->conn);
615   netconn_write(com->conn, com->args[2], strlen(com->args[2]), NETCONN_COPY);
616   sendstr(NEWLINE, com->conn);
617 
618   conns[i] = netconn_new(NETCONN_UDP);
619   if (conns[i] == NULL) {
620     sendstr("Could not create connection identifier (out of memory)."NEWLINE, com->conn);
621     return ESUCCESS;
622   }
623 
624   err = netconn_connect(conns[i], &ipaddr, rport);
625   if (err != ERR_OK) {
626     netconn_delete(conns[i]);
627     conns[i] = NULL;
628     sendstr("Could not connect to remote host: ", com->conn);
629 #ifdef LWIP_DEBUG
630     sendstr(lwip_strerr(err), com->conn);
631 #else
632     sendstr("(debugging must be turned on for error message to appear)", com->conn);
633 #endif /* LWIP_DEBUG */
634     sendstr(NEWLINE, com->conn);
635     return ESUCCESS;
636   }
637 
638   err = netconn_bind(conns[i], IP_ADDR_ANY, lport);
639   if (err != ERR_OK) {
640     netconn_delete(conns[i]);
641     conns[i] = NULL;
642     sendstr("Could not bind: ", com->conn);
643 #ifdef LWIP_DEBUG
644     sendstr(lwip_strerr(err), com->conn);
645 #else
646     sendstr("(debugging must be turned on for error message to appear)", com->conn);
647 #endif /* LWIP_DEBUG */
648     sendstr(NEWLINE, com->conn);
649     return ESUCCESS;
650   }
651 
652   sendstr("Connection set up, connection identifier is ", com->conn);
653   snprintf((char *)buffer, sizeof(buffer), "%d"NEWLINE, i);
654   netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
655 
656   return ESUCCESS;
657 }
658 /*-----------------------------------------------------------------------------------*/
659 static s8_t
com_udpl(struct command * com)660 com_udpl(struct command *com)
661 {
662   ip_addr_t ipaddr;
663   u16_t lport, rport;
664   int i;
665   err_t err;
666   long tmp;
667 
668   tmp = strtol(com->args[0], NULL, 10);
669   if((tmp < 0) || (tmp > 0xffff)) {
670     sendstr("Invalid port number."NEWLINE, com->conn);
671     return ESUCCESS;
672   }
673   lport = (u16_t)tmp;
674   if (ipaddr_aton(com->args[1], &ipaddr) == -1) {
675     sendstr(strerror(errno), com->conn);
676     return ESYNTAX;
677   }
678   tmp = strtol(com->args[2], NULL, 10);
679   if((tmp < 0) || (tmp > 0xffff)) {
680     sendstr("Invalid port number."NEWLINE, com->conn);
681     return ESUCCESS;
682   }
683   rport = (u16_t)tmp;
684 
685   /* Find the first unused connection in conns. */
686   for(i = 0; i < NCONNS && conns[i] != NULL; i++);
687 
688   if (i == NCONNS) {
689     sendstr("No more connections available, sorry."NEWLINE, com->conn);
690     return ESUCCESS;
691   }
692 
693   sendstr("Setting up UDP-Lite connection from port ", com->conn);
694   netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
695   sendstr(" to ", com->conn);
696   netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
697   sendstr(":", com->conn);
698   netconn_write(com->conn, com->args[2], strlen(com->args[2]), NETCONN_COPY);
699   sendstr(NEWLINE, com->conn);
700 
701   conns[i] = netconn_new(NETCONN_UDPLITE);
702   if (conns[i] == NULL) {
703     sendstr("Could not create connection identifier (out of memory)."NEWLINE, com->conn);
704     return ESUCCESS;
705   }
706 
707   err = netconn_connect(conns[i], &ipaddr, rport);
708   if (err != ERR_OK) {
709     netconn_delete(conns[i]);
710     conns[i] = NULL;
711     sendstr("Could not connect to remote host: ", com->conn);
712 #ifdef LWIP_DEBUG
713     sendstr(lwip_strerr(err), com->conn);
714 #else
715     sendstr("(debugging must be turned on for error message to appear)", com->conn);
716 #endif /* LWIP_DEBUG */
717     sendstr(NEWLINE, com->conn);
718     return ESUCCESS;
719   }
720 
721   err = netconn_bind(conns[i], IP_ADDR_ANY, lport);
722   if (err != ERR_OK) {
723     netconn_delete(conns[i]);
724     conns[i] = NULL;
725     sendstr("Could not bind: ", com->conn);
726 #ifdef LWIP_DEBUG
727     sendstr(lwip_strerr(err), com->conn);
728 #else
729     sendstr("(debugging must be turned on for error message to appear)", com->conn);
730 #endif /* LWIP_DEBUG */
731     sendstr(NEWLINE, com->conn);
732     return ESUCCESS;
733   }
734 
735   sendstr("Connection set up, connection identifier is ", com->conn);
736   snprintf((char *)buffer, sizeof(buffer), "%d"NEWLINE, i);
737   netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
738 
739   return ESUCCESS;
740 }
741 /*-----------------------------------------------------------------------------------*/
742 static s8_t
com_udpn(struct command * com)743 com_udpn(struct command *com)
744 {
745   ip_addr_t ipaddr;
746   u16_t lport, rport;
747   int i;
748   err_t err;
749   long tmp;
750 
751   tmp = strtol(com->args[0], NULL, 10);
752   if((tmp < 0) || (tmp > 0xffff)) {
753     sendstr("Invalid port number."NEWLINE, com->conn);
754     return ESUCCESS;
755   }
756   lport = (u16_t)tmp;
757   if (ipaddr_aton(com->args[1], &ipaddr) == -1) {
758     sendstr(strerror(errno), com->conn);
759     return ESYNTAX;
760   }
761   tmp = strtol(com->args[2], NULL, 10);
762   if((tmp < 0) || (tmp > 0xffff)) {
763     sendstr("Invalid port number."NEWLINE, com->conn);
764     return ESUCCESS;
765   }
766   rport = (u16_t)tmp;
767 
768   /* Find the first unused connection in conns. */
769   for(i = 0; i < NCONNS && conns[i] != NULL; i++);
770 
771   if (i == NCONNS) {
772     sendstr("No more connections available, sorry."NEWLINE, com->conn);
773     return ESUCCESS;
774   }
775 
776   sendstr("Setting up UDP connection without checksums from port ", com->conn);
777   netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
778   sendstr(" to ", com->conn);
779   netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
780   sendstr(":", com->conn);
781   netconn_write(com->conn, com->args[2], strlen(com->args[2]), NETCONN_COPY);
782   sendstr(NEWLINE, com->conn);
783 
784   conns[i] = netconn_new(NETCONN_UDPNOCHKSUM);
785   if (conns[i] == NULL) {
786     sendstr("Could not create connection identifier (out of memory)."NEWLINE, com->conn);
787     return ESUCCESS;
788   }
789 
790   err = netconn_connect(conns[i], &ipaddr, rport);
791   if (err != ERR_OK) {
792     netconn_delete(conns[i]);
793     conns[i] = NULL;
794     sendstr("Could not connect to remote host: ", com->conn);
795 #ifdef LWIP_DEBUG
796     sendstr(lwip_strerr(err), com->conn);
797 #else
798     sendstr("(debugging must be turned on for error message to appear)", com->conn);
799 #endif /* LWIP_DEBUG */
800     sendstr(NEWLINE, com->conn);
801     return ESUCCESS;
802   }
803 
804   err = netconn_bind(conns[i], IP_ADDR_ANY, lport);
805   if (err != ERR_OK) {
806     netconn_delete(conns[i]);
807     conns[i] = NULL;
808     sendstr("Could not bind: ", com->conn);
809 #ifdef LWIP_DEBUG
810     sendstr(lwip_strerr(err), com->conn);
811 #else
812     sendstr("(debugging must be turned on for error message to appear)", com->conn);
813 #endif /* LWIP_DEBUG */
814     sendstr(NEWLINE, com->conn);
815     return ESUCCESS;
816   }
817 
818   sendstr("Connection set up, connection identifier is ", com->conn);
819   snprintf((char *)buffer, sizeof(buffer), "%d"NEWLINE, i);
820   netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
821 
822   return ESUCCESS;
823 }
824 /*-----------------------------------------------------------------------------------*/
825 static s8_t
com_udpb(struct command * com)826 com_udpb(struct command *com)
827 {
828   ip_addr_t ipaddr;
829 #if LWIP_IPV4
830   u16_t lport;
831 #endif /* LWIP_IPV4 */
832   u16_t rport;
833   int i;
834   err_t err;
835   long tmp;
836 
837   tmp = strtol(com->args[0], NULL, 10);
838   if((tmp < 0) || (tmp > 0xffff)) {
839     sendstr("Invalid port number."NEWLINE, com->conn);
840     return ESUCCESS;
841   }
842 #if LWIP_IPV4
843   lport = (u16_t)tmp;
844 #endif /* LWIP_IPV4 */
845   if (ipaddr_aton(com->args[1], &ipaddr) == -1) {
846     sendstr(strerror(errno), com->conn);
847     return ESYNTAX;
848   }
849   tmp = strtol(com->args[2], NULL, 10);
850   if((tmp < 0) || (tmp > 0xffff)) {
851     sendstr("Invalid port number."NEWLINE, com->conn);
852     return ESUCCESS;
853   }
854   rport = (u16_t)tmp;
855 
856   /* Find the first unused connection in conns. */
857   for(i = 0; i < NCONNS && conns[i] != NULL; i++);
858 
859   if (i == NCONNS) {
860     sendstr("No more connections available, sorry."NEWLINE, com->conn);
861     return ESUCCESS;
862   }
863 
864   sendstr("Setting up UDP broadcast connection from port ", com->conn);
865   netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
866   sendstr(" to ", com->conn);
867   netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
868   sendstr(NEWLINE, com->conn);
869 
870   conns[i] = netconn_new(NETCONN_UDP);
871   if (conns[i] == NULL) {
872     sendstr("Could not create connection identifier (out of memory)."NEWLINE, com->conn);
873     return ESUCCESS;
874   }
875 
876   err = netconn_connect(conns[i], &ipaddr, rport);
877   if (err != ERR_OK) {
878     netconn_delete(conns[i]);
879     conns[i] = NULL;
880     sendstr("Could not connect to remote host: ", com->conn);
881 #ifdef LWIP_DEBUG
882     sendstr(lwip_strerr(err), com->conn);
883 #else
884     sendstr("(debugging must be turned on for error message to appear)", com->conn);
885 #endif /* LWIP_DEBUG */
886     sendstr(NEWLINE, com->conn);
887     return ESUCCESS;
888   }
889 
890 #if LWIP_IPV4
891   if (IP_IS_V6_VAL(ipaddr)) {
892     err = netconn_bind(conns[i], &ip_addr_broadcast, lport);
893     if (err != ERR_OK) {
894       netconn_delete(conns[i]);
895       conns[i] = NULL;
896       sendstr("Could not bind: ", com->conn);
897 #ifdef LWIP_DEBUG
898       sendstr(lwip_strerr(err), com->conn);
899 #else
900       sendstr("(debugging must be turned on for error message to appear)", com->conn);
901 #endif /* LWIP_DEBUG */
902       sendstr(NEWLINE, com->conn);
903       return ESUCCESS;
904     }
905   }
906 #endif /* LWIP_IPV4 */
907 
908   sendstr("Connection set up, connection identifier is ", com->conn);
909   snprintf((char *)buffer, sizeof(buffer), "%d"NEWLINE, i);
910   netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
911 
912   return ESUCCESS;
913 }
914 /*-----------------------------------------------------------------------------------*/
915 static s8_t
com_usnd(struct command * com)916 com_usnd(struct command *com)
917 {
918   long i;
919   err_t err;
920   struct netbuf *buf;
921   char *mem;
922   u16_t len;
923   size_t tmp;
924 
925   i = strtol(com->args[0], NULL, 10);
926 
927   if (i > NCONNS) {
928     sendstr("Connection identifier too high."NEWLINE, com->conn);
929     return ESUCCESS;
930   }
931 
932   if (conns[i] == NULL) {
933     sendstr("Connection identifier not in use."NEWLINE, com->conn);
934     return ESUCCESS;
935   }
936   tmp = strlen(com->args[1]) + 1;
937   if (tmp > 0xffff) {
938     sendstr("Invalid length."NEWLINE, com->conn);
939     return ESUCCESS;
940   }
941   len = (u16_t)tmp;
942 
943   buf = netbuf_new();
944   mem = (char *)netbuf_alloc(buf, len);
945   if (mem == NULL) {
946     sendstr("Could not allocate memory for sending."NEWLINE, com->conn);
947     return ESUCCESS;
948   }
949   strncpy(mem, com->args[1], len);
950   err = netconn_send(conns[i], buf);
951   netbuf_delete(buf);
952   if (err != ERR_OK) {
953     sendstr("Could not send data: ", com->conn);
954 #ifdef LWIP_DEBUG
955     sendstr(lwip_strerr(err), com->conn);
956 #else
957     sendstr("(debugging must be turned on for error message to appear)", com->conn);
958 #endif /* LWIP_DEBUG */
959     sendstr(NEWLINE, com->conn);
960     return ESUCCESS;
961   }
962 
963   sendstr("Data sent."NEWLINE, com->conn);
964   return ESUCCESS;
965 }
966 /*-----------------------------------------------------------------------------------*/
967 #if LWIP_SOCKET
968 /*-----------------------------------------------------------------------------------*/
969 static s8_t
com_idxtoname(struct command * com)970 com_idxtoname(struct command *com)
971 {
972   long i = strtol(com->args[0], NULL, 10);
973 
974   if (lwip_if_indextoname((unsigned int)i, (char *)buffer)) {
975     netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
976     sendstr(NEWLINE, com->conn);
977   } else {
978     snprintf((char *)buffer, sizeof(buffer), "if_indextoname() failed: %d"NEWLINE, errno);
979     netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
980   }
981   return ESUCCESS;
982 }
983 /*-----------------------------------------------------------------------------------*/
984 static s8_t
com_nametoidx(struct command * com)985 com_nametoidx(struct command *com)
986 {
987   unsigned int idx = lwip_if_nametoindex(com->args[0]);
988 
989   if (idx) {
990     snprintf((char *)buffer, sizeof(buffer), "%u"NEWLINE, idx);
991     netconn_write(com->conn, buffer, strlen((const char *)buffer), NETCONN_COPY);
992   } else {
993     sendstr("No interface found"NEWLINE, com->conn);
994   }
995   return ESUCCESS;
996 }
997 #endif /* LWIP_SOCKET */
998 /*-----------------------------------------------------------------------------------*/
999 #if LWIP_DNS
1000 static s8_t
com_gethostbyname(struct command * com)1001 com_gethostbyname(struct command *com)
1002 {
1003   ip_addr_t addr;
1004   err_t err = netconn_gethostbyname(com->args[0], &addr);
1005 
1006   if (err == ERR_OK) {
1007     if (ipaddr_ntoa_r(&addr, (char *)buffer, sizeof(buffer))) {
1008       sendstr("Host found: ", com->conn);
1009       sendstr((char *)buffer, com->conn);
1010       sendstr(NEWLINE, com->conn);
1011     } else {
1012         sendstr("ipaddr_ntoa_r failed", com->conn);
1013     }
1014   } else {
1015     sendstr("No host found"NEWLINE, com->conn);
1016   }
1017   return ESUCCESS;
1018 }
1019 #endif /* LWIP_DNS */
1020 /*-----------------------------------------------------------------------------------*/
1021 static s8_t
com_help(struct command * com)1022 com_help(struct command *com)
1023 {
1024   sendstr(help_msg1, com->conn);
1025   sendstr(help_msg2, com->conn);
1026   sendstr(help_msg3, com->conn);
1027   return ESUCCESS;
1028 }
1029 /*-----------------------------------------------------------------------------------*/
1030 static s8_t
parse_command(struct command * com,u32_t len)1031 parse_command(struct command *com, u32_t len)
1032 {
1033   u16_t i;
1034   u16_t bufp;
1035 
1036   if (strncmp((const char *)buffer, "open", 4) == 0) {
1037     com->exec = com_open;
1038     com->nargs = 2;
1039   } else if (strncmp((const char *)buffer, "lstn", 4) == 0) {
1040     com->exec = com_lstn;
1041     com->nargs = 1;
1042   } else if (strncmp((const char *)buffer, "acpt", 4) == 0) {
1043     com->exec = com_acpt;
1044     com->nargs = 1;
1045   } else if (strncmp((const char *)buffer, "clos", 4) == 0) {
1046     com->exec = com_clos;
1047     com->nargs = 1;
1048 #if LWIP_STATS
1049   } else if (strncmp((const char *)buffer, "stat", 4) == 0) {
1050     com->exec = com_stat;
1051     com->nargs = 0;
1052 #endif
1053   } else if (strncmp((const char *)buffer, "send", 4) == 0) {
1054     com->exec = com_send;
1055     com->nargs = 2;
1056   } else if (strncmp((const char *)buffer, "recv", 4) == 0) {
1057     com->exec = com_recv;
1058     com->nargs = 1;
1059   } else if (strncmp((const char *)buffer, "udpc", 4) == 0) {
1060     com->exec = com_udpc;
1061     com->nargs = 3;
1062   } else if (strncmp((const char *)buffer, "udpb", 4) == 0) {
1063     com->exec = com_udpb;
1064     com->nargs = 2;
1065   } else if (strncmp((const char *)buffer, "udpl", 4) == 0) {
1066     com->exec = com_udpl;
1067     com->nargs = 3;
1068   } else if (strncmp((const char *)buffer, "udpn", 4) == 0) {
1069     com->exec = com_udpn;
1070     com->nargs = 3;
1071   } else if (strncmp((const char *)buffer, "usnd", 4) == 0) {
1072     com->exec = com_usnd;
1073     com->nargs = 2;
1074 #if LWIP_SOCKET
1075   } else if (strncmp((const char *)buffer, "idxtoname", 9) == 0) {
1076     com->exec = com_idxtoname;
1077     com->nargs = 1;
1078   } else if (strncmp((const char *)buffer, "nametoidx", 9) == 0) {
1079     com->exec = com_nametoidx;
1080     com->nargs = 1;
1081 #endif /* LWIP_SOCKET */
1082 #if LWIP_DNS
1083   } else if (strncmp((const char *)buffer, "gethostnm", 9) == 0) {
1084     com->exec = com_gethostbyname;
1085     com->nargs = 1;
1086 #endif /* LWIP_DNS */
1087   } else if (strncmp((const char *)buffer, "help", 4) == 0) {
1088     com->exec = com_help;
1089     com->nargs = 0;
1090   } else if (strncmp((const char *)buffer, "quit", 4) == 0) {
1091     printf("quit"NEWLINE);
1092     return ECLOSED;
1093   } else {
1094     return ESYNTAX;
1095   }
1096 
1097   if (com->nargs == 0) {
1098     return ESUCCESS;
1099   }
1100   bufp = 0;
1101   for(; bufp < len && buffer[bufp] != ' '; bufp++);
1102   for(i = 0; i < 10; i++) {
1103     for(; bufp < len && buffer[bufp] == ' '; bufp++);
1104     if (buffer[bufp] == '\r' ||
1105        buffer[bufp] == '\n') {
1106       buffer[bufp] = 0;
1107       if (i < com->nargs - 1) {
1108         return ETOOFEW;
1109       }
1110       if (i > com->nargs - 1) {
1111         return ETOOMANY;
1112       }
1113       break;
1114     }
1115     if (bufp > len) {
1116       return ETOOFEW;
1117     }
1118     com->args[i] = (char *)&buffer[bufp];
1119     for(; bufp < len && buffer[bufp] != ' ' && buffer[bufp] != '\r' &&
1120       buffer[bufp] != '\n'; bufp++) {
1121       if (buffer[bufp] == '\\') {
1122         buffer[bufp] = ' ';
1123       }
1124     }
1125     if (bufp > len) {
1126       return ESYNTAX;
1127     }
1128     buffer[bufp] = 0;
1129     bufp++;
1130     if (i == com->nargs - 1) {
1131       break;
1132     }
1133 
1134   }
1135 
1136   return ESUCCESS;
1137 }
1138 /*-----------------------------------------------------------------------------------*/
1139 static void
shell_error(s8_t err,struct netconn * conn)1140 shell_error(s8_t err, struct netconn *conn)
1141 {
1142   switch (err) {
1143   case ESYNTAX:
1144     sendstr("## Syntax error"NEWLINE, conn);
1145     break;
1146   case ETOOFEW:
1147     sendstr("## Too few arguments to command given"NEWLINE, conn);
1148     break;
1149   case ETOOMANY:
1150     sendstr("## Too many arguments to command given"NEWLINE, conn);
1151     break;
1152   case ECLOSED:
1153     sendstr("## Connection closed"NEWLINE, conn);
1154     break;
1155   default:
1156     /* unknown error, don't assert here */
1157     break;
1158   }
1159 }
1160 /*-----------------------------------------------------------------------------------*/
1161 static void
prompt(struct netconn * conn)1162 prompt(struct netconn *conn)
1163 {
1164   sendstr("> ", conn);
1165 }
1166 /*-----------------------------------------------------------------------------------*/
1167 static void
shell_main(struct netconn * conn)1168 shell_main(struct netconn *conn)
1169 {
1170   struct pbuf *p;
1171   u16_t len = 0, cur_len;
1172   struct command com;
1173   s8_t err;
1174   int i;
1175   err_t ret;
1176 #if SHELL_ECHO
1177   void *echomem;
1178 #endif /* SHELL_ECHO */
1179 
1180   do {
1181     ret = netconn_recv_tcp_pbuf(conn, &p);
1182     if (ret == ERR_OK) {
1183       pbuf_copy_partial(p, &buffer[len], (u16_t)(BUFSIZE - len), 0);
1184       cur_len = p->tot_len;
1185       len = (u16_t)(len + cur_len);
1186       if ((len < cur_len) || (len > BUFSIZE)) {
1187         len = BUFSIZE;
1188       }
1189 #if SHELL_ECHO
1190       echomem = mem_malloc(cur_len);
1191       if (echomem != NULL) {
1192         pbuf_copy_partial(p, echomem, cur_len, 0);
1193         netconn_write(conn, echomem, cur_len, NETCONN_COPY);
1194         mem_free(echomem);
1195       }
1196 #endif /* SHELL_ECHO */
1197       pbuf_free(p);
1198       if (((len > 0) && ((buffer[len-1] == '\r') || (buffer[len-1] == '\n'))) ||
1199           (len >= BUFSIZE)) {
1200         if (buffer[0] != 0xff &&
1201            buffer[1] != 0xfe) {
1202           err = parse_command(&com, len);
1203           if (err == ESUCCESS) {
1204             com.conn = conn;
1205             err = com.exec(&com);
1206           }
1207           if (err == ECLOSED) {
1208             printf("Closed"NEWLINE);
1209             shell_error(err, conn);
1210             goto close;
1211           }
1212           if (err != ESUCCESS) {
1213             shell_error(err, conn);
1214           }
1215         } else {
1216           sendstr(NEWLINE NEWLINE
1217                   "lwIP simple interactive shell."NEWLINE
1218                   "(c) Copyright 2001, Swedish Institute of Computer Science."NEWLINE
1219                   "Written by Adam Dunkels."NEWLINE
1220                   "For help, try the \"help\" command."NEWLINE, conn);
1221         }
1222         if (ret == ERR_OK) {
1223           prompt(conn);
1224         }
1225         len = 0;
1226       }
1227     }
1228   } while (ret == ERR_OK);
1229   printf("err %s"NEWLINE, lwip_strerr(ret));
1230 
1231 close:
1232   netconn_close(conn);
1233 
1234   for(i = 0; i < NCONNS; i++) {
1235     if (conns[i] != NULL) {
1236       netconn_delete(conns[i]);
1237     }
1238     conns[i] = NULL;
1239   }
1240 }
1241 /*-----------------------------------------------------------------------------------*/
1242 static void
shell_thread(void * arg)1243 shell_thread(void *arg)
1244 {
1245   struct netconn *conn, *newconn;
1246   err_t err;
1247   LWIP_UNUSED_ARG(arg);
1248 
1249 #if LWIP_IPV6
1250   conn = netconn_new(NETCONN_TCP_IPV6);
1251   LWIP_ERROR("shell: invalid conn", (conn != NULL), return;);
1252   err = netconn_bind(conn, IP6_ADDR_ANY, 23);
1253 #else /* LWIP_IPV6 */
1254   conn = netconn_new(NETCONN_TCP);
1255   LWIP_ERROR("shell: invalid conn", (conn != NULL), return;);
1256   err = netconn_bind(conn, IP_ADDR_ANY, 23);
1257 #endif /* LWIP_IPV6 */
1258   LWIP_ERROR("shell: netconn_bind failed", (err == ERR_OK), netconn_delete(conn); return;);
1259   err = netconn_listen(conn);
1260   LWIP_ERROR("shell: netconn_listen failed", (err == ERR_OK), netconn_delete(conn); return;);
1261 
1262   while (1) {
1263     err = netconn_accept(conn, &newconn);
1264     if (err == ERR_OK) {
1265       shell_main(newconn);
1266       netconn_delete(newconn);
1267     }
1268   }
1269 }
1270 /*-----------------------------------------------------------------------------------*/
1271 void
shell_init(void)1272 shell_init(void)
1273 {
1274   sys_thread_new("shell_thread", shell_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
1275 }
1276 
1277 #endif /* LWIP_NETCONN && LWIP_TCP */
1278