shell.c 37 KB

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