1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2022 Huawei Device Co., Ltd. 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, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "../core/ipv4/etharp.c" /* for arp_table */
33 #define icmp6_hdr netinet_icmp6_hdr
34 #include <netinet/icmp6.h>
35 #undef icmp6_hdr
36 #include "lwip/fixme.h"
37 #include "lwip/opt.h"
38
39 #if LWIP_ENABLE_LOS_SHELL_CMD
40 #include "lwip/api.h"
41 #include "lwip/tcpip.h"
42 #include "lwip/netif.h"
43 #include "lwip/netdb.h"
44 #include "lwip/stats.h"
45 #include "lwip/err.h"
46 #include "lwip/inet.h"
47 #include "netif/etharp.h"
48 #include "lwip/ip_addr.h"
49 #include "lwip/ip6_addr.h"
50 #include "lwip/icmp.h"
51 #include "lwip/priv/nd6_priv.h"
52 #include "lwip/sockets.h"
53 #include "lwip/inet_chksum.h"
54 #include "lwip/raw.h"
55 #include "los_config.h"
56 #include <string.h>
57 #include "limits.h"
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <errno.h>
61 #include <time.h>
62 #include <ctype.h>
63 #include <poll.h>
64
65 #include "lwip/api_shell.h"
66
67 #include "lwip/dns.h"
68 #include "lwip/udp.h"
69 #include "lwip/priv/tcp_priv.h"
70
71 #include "lwip/dhcp.h"
72 #include "lwip/netifapi.h"
73 #include "los_strnlen_user.h"
74 #include "linux/kernel.h"
75 #ifdef LOSCFG_SHELL
76 #include "shcmd.h"
77 #include "shell.h"
78 #endif
79
80 #define LWIP_STATIC static
81
82 #if LWIP_ARP
83 extern sys_sem_t ip_conflict_detect;
84 #endif
85 extern volatile int tcpip_init_finish;
86 extern const char *const tcp_state_str[];
87 extern int get_unused_socket_num(void);
88
89 #if LWIP_IPV6
90 #define LWIP_MAX_PING6_ARG_COUNT 64
91 #define LWIP_PING6_STANDARD_PKT_SIZE 56
92 #define LWIP_PING6_STARTING_SEQ_NUM 0x2255
93 #define LWIP_PING6_OUT_OF_ORDER_MAGNITUDE 1
94
95 #define LWIP_PING6_COUNT_ARG 1
96 #define LWIP_PING6_SOURCE_ADDRESS_ARG 2
97 #define LWIP_PING6_INTERFACE_ARG 4
98 #define LWIP_PING6_HOSTNAME_ARG 8
99 #define LWIP_PING6_DEFAULT_SOCKET 16
100 #endif
101
102 /* Forward Declarations [START] */
103 #ifndef LWIP_TESTBED
104 LWIP_STATIC
105 #endif
106 int print_netif(struct netif *netif, char *print_buf, unsigned int buf_len);
107
108 #ifndef LWIP_TESTBED
109 LWIP_STATIC
110 #endif
111 void lwip_ifconfig_show_internal(void *arg);
112
113 #ifndef LWIP_TESTBED
114 LWIP_STATIC
115 #endif
116 void lwip_ifconfig_internal(void *arg);
117
118 void lwip_printsize(size_t size);
119 LWIP_STATIC void lwip_ifconfig_usage(const char *cmd);
120
121 #ifndef LWIP_TESTBED
122 LWIP_STATIC
123 #endif
124 void lwip_arp_show_internal(struct netif *netif, char *printf_buf, unsigned int buf_len);
125
126 #ifndef LWIP_TESTBED
127 LWIP_STATIC
128 #endif
129 void lwip_arp_internal(void *arg);
130
131 LWIP_STATIC void lwip_arp_usage(const char *cmd);
132 void ifup_internal(void *arg);
133 void ifdown_internal(void *arg);
134
135 #if LWIP_DNS
136 LWIP_STATIC unsigned int get_hostip(const char *hname);
137
138 #ifndef LWIP_TESTBED
139 LWIP_STATIC
140 #endif
141 struct hostent *gethostnameinfo(const char *host);
142
143 #endif /* LWIP_DNS */
144
145 #ifdef LWIP_DEBUG_INFO
146 LWIP_STATIC u32_t netdebug_memp(int argc, const char **argv);
147 LWIP_STATIC u32_t netdebug_sock(int argc, const char **argv);
148 u32_t osShellNetDebug(int argc, const char **argv);
149 u32_t osShellIpDebug(int argc, const char **argv);
150 #endif /* LWIP_DEBUG_INFO */
151 #if LWIP_IPV6
152 /* Holds params for ping6 task */
153 typedef struct ping6_args {
154 u8_t args_found;
155 u8_t interface_index;
156 u8_t host_index;
157 u8_t pad;
158 u32_t pingcount;
159 ip6_addr_t src_addr;
160 ip6_addr_t dst_addr;
161 } ping6_args_t;
162
163 /* Holds stats for ongoing ping6 task */
164 typedef struct ping6_stats {
165 u32_t flag;
166 u32_t min_rtt;
167 u32_t max_rtt;
168 float avg_rtt;
169 } ping6_stats_t;
170 LWIP_STATIC void update_ping6_stats(ping6_stats_t *ping6_stats, u32_t rtt, u32_t nreceived);
171 LWIP_STATIC int parse_args_ping6(int argc, const char **argv, ping6_args_t *ping6_params);
172
173 u32_t osShellPing6(int argc, const char **argv);
174 LWIP_STATIC int create_ping6_socket(u8_t type, const void *param);
175 LWIP_STATIC const char *convert_icmpv6_err_to_string(u8_t err_type);
176 #endif /* LWIP_IPV6 */
177 u32_t osTcpserver(int argc, const char **argv);
178 void udpserver(int argc, const char **argv);
179 void tcp_access(int sockfd);
180 #if LWIP_IPV6
181 int netstat_get_udp_sendQLen6(struct udp_pcb *udppcb, struct pbuf *udpbuf);
182 int netstat_udp_sendq6(struct udp_pcb *upcb);
183 #endif
184 #if LWIP_IPV4
185 int netstat_get_udp_sendQLen(struct udp_pcb *udppcb, struct pbuf *udpbuf);
186 #endif
187 int netstat_tcp_sendq(struct tcp_pcb *tpcb);
188 int netstat_tcp_recvq(struct tcp_pcb *tpcb);
189 int netstat_netconn_recvq(const struct netconn *conn);
190
191 int netstat_udp_sendq(struct udp_pcb *upcb);
192 int netstat_netconn_sendq(struct netconn *conn);
193 /* Forward Declarations [END] */
194
195 #define IFCONFIG_OPTION_SET_IP (1)
196 #define IFCONFIG_OPTION_SET_NETMASK (1 << 1)
197 #define IFCONFIG_OPTION_SET_GW (1 << 2)
198 #define IFCONFIG_OPTION_SET_HW (1 << 3)
199 #define IFCONFIG_OPTION_SET_UP (1 << 4)
200 #define IFCONFIG_OPTION_SET_DOWN (1 << 5)
201 #define IFCONFIG_OPTION_SET_MTU (1 << 6)
202 #define IFCONFIG_OPTION_DEL_IP (1 << 7)
203
204 #define NETSTAT_ENTRY_SIZE 120
205 #define MAX_NETSTAT_ENTRY (NETSTAT_ENTRY_SIZE * (MEMP_NUM_TCP_PCB + MEMP_NUM_UDP_PCB + MEMP_NUM_TCP_PCB_LISTEN + 1))
206
207 #define PRINT_BUF_LEN 1024
208 #define MAX_MACADDR_STRING_LENGTH 18 /* including NULL */
209
210 #define CONVERT_STRING_TO_HEX(_src, _dest) \
211 { \
212 const char *_srcString = (char *)_src; \
213 _dest = 0; \
214 while (*_srcString) { \
215 _dest = (unsigned char)((_dest << 4) & 0xFF); \
216 if ((*_srcString >= 48) && (*_srcString <= 57)) /* between 0 to 9 */ \
217 _dest |= (unsigned char)(*_srcString - 48); \
218 else if ((*_srcString >= 65 && *_srcString <= 70)) /* between A to F */ \
219 _dest |= (unsigned char)((*_srcString - 65) + 10); \
220 else if ((*_srcString >= 97 && *_srcString <= 102)) /* between a to f */ \
221 _dest |= (unsigned char)((*_srcString - 97) + 10); \
222 else break; \
223 ++_srcString; \
224 } \
225 }
226
227 #define ERR_IFCONFIG_STRING_PUT(ret, str) \
228 do { \
229 (ret) = snprintf_s(ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len, \
230 PRINT_BUF_LEN - ifconfig_cmd->print_len, \
231 ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), (str)); \
232 if (((ret) > 0) && ((unsigned int)(ret) < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) \
233 ifconfig_cmd->print_len += (unsigned int)(ret); \
234 } while (0) \
235
236 #define LWIP_MSECS_TO_SECS(time_in_msecs) (time_in_msecs / 1000)
237 struct ifconfig_option {
238 char iface[IFNAMSIZ];
239 unsigned int option;
240 ip_addr_t ip_addr;
241 ip_addr_t netmask;
242 ip_addr_t gw;
243 unsigned char ethaddr[6];
244 u16_t mtu;
245 /* when using telnet, print to the telnet socket will result in system */
246 /* deadlock. So we cache the print data to a buf, and when the tcpip */
247 /* callback returns, then print the data out to the telnet socket */
248 sys_sem_t cb_completed;
249 char cb_print_buf[PRINT_BUF_LEN];
250 unsigned int print_len;
251 };
252
253 struct netstat_data {
254 s8_t *netstat_out_buf;
255 u32_t netstat_out_buf_len;
256 u32_t netstat_out_buf_updated_len;
257 sys_sem_t cb_completed;
258 };
259
260 struct if_cmd_data {
261 char *if_name;
262 err_t err;
263 sys_sem_t cb_completed;
264 };
265
266 #ifndef LWIP_TESTBED
267 LWIP_STATIC
268 #endif
print_netif(struct netif * netif,char * print_buf,unsigned int buf_len)269 int print_netif(struct netif *netif, char *print_buf, unsigned int buf_len)
270 {
271 int i, ret;
272 char *tmp = print_buf;
273 #if LWIP_IPV6
274 char *addr = NULL;
275 #endif
276
277 if (buf_len < 1) {
278 goto out;
279 }
280 if (netif->link_layer_type == LOOPBACK_IF) {
281 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%.2s\t", netif->name);
282 } else {
283 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%s\t", netif_get_name(netif));
284 }
285 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
286 goto out;
287 tmp += ret;
288 buf_len -= (unsigned int)ret;
289 #if LWIP_IPV4
290 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "ip:%s ", ipaddr_ntoa(&netif->ip_addr));
291 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
292 goto out;
293 tmp += ret;
294 buf_len -= (unsigned int)ret;
295
296 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "netmask:%s ", ipaddr_ntoa(&netif->netmask));
297 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
298 goto out;
299 tmp += ret;
300 buf_len -= (unsigned int)ret;
301
302 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "gateway:%s\n", ipaddr_ntoa(&netif->gw));
303 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
304 goto out;
305 tmp += ret;
306 buf_len -= (unsigned int)ret;
307 #endif
308
309 #if LWIP_IPV6
310 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
311 /* only PREFERRED addresses are displyaed */
312 if (!ip6_addr_isvalid(netif->ip6_addr_state[i])) {
313 continue;
314 }
315 addr = ip6addr_ntoa((const ip6_addr_t *)&netif->ip6_addr[i]);
316 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tip6: %s/64\n", addr ? addr : "::");
317 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
318 goto out;
319 tmp += ret;
320 buf_len -= (unsigned int)ret;
321 }
322 #endif
323
324 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tHWaddr ");
325 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
326 goto out;
327 tmp += ret;
328 buf_len -= (unsigned int)ret;
329
330 for (i = 0; i < netif->hwaddr_len - 1; i++) {
331 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%02x:", netif->hwaddr[i]);
332 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
333 goto out;
334 tmp += ret;
335 buf_len -= (unsigned int)ret;
336 }
337
338 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%02x", netif->hwaddr[i]);
339 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
340 goto out;
341 tmp += ret;
342 buf_len -= (unsigned int)ret;
343
344 ret = snprintf_s(tmp, buf_len, (buf_len - 1), " MTU:%d %s", netif->mtu,
345 (netif->flags & NETIF_FLAG_UP) ? "Running" : "Stop");
346 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
347 goto out;
348 tmp += ret;
349 buf_len -= (unsigned int)ret;
350
351 if (netif_default == netif && netif_is_up(netif)) {
352 ret = snprintf_s(tmp, buf_len, (buf_len - 1), " %s", "Default");
353 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
354 goto out;
355 tmp += ret;
356 buf_len -= (unsigned int)ret;
357 }
358
359 ret = snprintf_s(tmp, buf_len, (buf_len - 1), " %s\n",
360 (netif->flags & NETIF_FLAG_LINK_UP) ? "Link UP" : "Link Down");
361 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
362 goto out;
363 tmp += ret;
364
365 #if MIB2_STATS
366 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tRX packets:%u ",
367 netif->mib2_counters.ifinucastpkts + netif->mib2_counters.ifinnucastpkts);
368 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
369 goto out;
370 tmp += ret;
371 buf_len -= (unsigned int)ret;
372
373 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "errors:%u ", netif->mib2_counters.ifinerrors);
374 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
375 goto out;
376 tmp += ret;
377 buf_len -= (unsigned int)ret;
378
379 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "dropped:%u ", netif->mib2_counters.ifindiscards);
380 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
381 goto out;
382 tmp += ret;
383 buf_len -= (unsigned int)ret;
384
385 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "overruns:%u\n", netif->mib2_counters.ifinoverruns);
386 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
387 goto out;
388 tmp += ret;
389 buf_len -= (unsigned int)ret;
390
391 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tTX packets:%u ",
392 netif->mib2_counters.ifoutucastpkts + netif->mib2_counters.ifoutnucastpkts);
393 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
394 goto out;
395 tmp += ret;
396 buf_len -= (unsigned int)ret;
397
398 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "errors:%u ", netif->mib2_counters.ifouterrors);
399 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
400 goto out;
401 tmp += ret;
402 buf_len -= (unsigned int)ret;
403
404 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "dropped:%u\n", netif->mib2_counters.ifoutdiscards);
405 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
406 goto out;
407 tmp += ret;
408 buf_len -= (unsigned int)ret;
409
410 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tRX bytes:%u ", netif->mib2_counters.ifinoctets);
411 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
412 goto out;
413 tmp += ret;
414 buf_len -= (unsigned int)ret;
415
416 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "TX bytes:%u\n", netif->mib2_counters.ifoutoctets);
417 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
418 goto out;
419 tmp += ret;
420 buf_len -= (unsigned int)ret;
421 #endif
422
423 out:
424 return (int)(tmp - print_buf);
425 }
426
427 #ifndef LWIP_TESTBED
428 LWIP_STATIC
429 #endif
lwip_ifconfig_show_internal(void * arg)430 void lwip_ifconfig_show_internal(void *arg)
431 {
432 struct netif *netif = NULL;
433 struct ifconfig_option *ifconfig_cmd = (struct ifconfig_option *)arg;
434 int ret;
435
436 if (netif_list == NULL) {
437 ret = snprintf_s(ifconfig_cmd->cb_print_buf, PRINT_BUF_LEN - ifconfig_cmd->print_len,
438 ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), "Device not init\n");
439 if ((ret > 0) && ((unsigned int)ret < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) {
440 ifconfig_cmd->print_len += (unsigned int)ret;
441 }
442 sys_sem_signal(&ifconfig_cmd->cb_completed);
443 return;
444 }
445
446 if (ifconfig_cmd->iface[0] == '\0') {
447 /* display all netif */
448 for (netif = netif_list; netif != NULL; netif = netif->next) {
449 ret = print_netif(netif, ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len,
450 PRINT_BUF_LEN - ifconfig_cmd->print_len);
451 ifconfig_cmd->print_len += (unsigned int)ret;
452 }
453 } else {
454 netif = netif_find(ifconfig_cmd->iface);
455 if (netif == NULL) {
456 ret = snprintf_s(ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len,
457 (PRINT_BUF_LEN - ifconfig_cmd->print_len),
458 ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), "Device not found\n");
459 if ((ret > 0) && ((unsigned int)ret < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) {
460 ifconfig_cmd->print_len += (unsigned int)ret;
461 }
462
463 sys_sem_signal(&ifconfig_cmd->cb_completed);
464 return;
465 }
466
467 ret = print_netif(netif, ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len,
468 PRINT_BUF_LEN - ifconfig_cmd->print_len);
469 ifconfig_cmd->print_len += (unsigned int)ret;
470 }
471 sys_sem_signal(&ifconfig_cmd->cb_completed);
472 }
473
474 #ifndef LWIP_TESTBED
475 LWIP_STATIC
476 #endif
lwip_ifconfig_internal(void * arg)477 void lwip_ifconfig_internal(void *arg)
478 {
479 struct ifconfig_option *ifconfig_cmd = NULL;
480 struct netif *netif = NULL;
481 ip_addr_t ip_addr;
482 ip_addr_t netmask;
483 ip_addr_t gw;
484 unsigned short mtu;
485 struct netif *loc_netif = NULL;
486 int ret;
487 s8_t idx;
488 err_t err;
489
490 ifconfig_cmd = (struct ifconfig_option *)arg;
491 netif = netif_find(ifconfig_cmd->iface);
492 if (netif == NULL) {
493 ERR_IFCONFIG_STRING_PUT(ret, "Device not found\n");
494 goto out;
495 }
496
497 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_UP) {
498 (void)netif_set_up(netif);
499 goto out;
500 } else if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_DOWN) {
501 (void)netif_set_down(netif);
502 goto out;
503 }
504
505 if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) ||
506 (ifconfig_cmd->option & IFCONFIG_OPTION_SET_NETMASK) ||
507 (ifconfig_cmd->option & IFCONFIG_OPTION_SET_HW)) {
508 (void)netif_set_down(netif);
509 }
510
511 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) {
512 ip_addr_set_val(&ip_addr, &(ifconfig_cmd->ip_addr));
513 if (IP_IS_V4_VAL(ifconfig_cmd->ip_addr)) {
514 /* check the address is not multicast/broadcast/0/loopback */
515 if (ip_addr_ismulticast_val(&ip_addr) || ip_addr_isbroadcast_val(&ip_addr, netif) ||
516 ip_addr_isany(&ip_addr) || ip_addr_isloopback(&ip_addr)) {
517 ERR_IFCONFIG_STRING_PUT(ret, "Don't set ip as a multicast/broadcast/0/loopback address!\n");
518 goto out;
519 }
520
521 /* reset gateway if new and previous ipaddr not in same net */
522 if (!ip_addr_netcmp_val(&ip_addr, &netif->ip_addr, ip_2_ip4(&netif->netmask))) {
523 ip_addr_set_zero(&netif->gw);
524 if (netif == netif_default) {
525 (void)netif_set_default(NULL);
526 }
527 }
528
529 /* lwip disallow two netif sit in same net at the same time */
530 loc_netif = netif_list;
531 while (loc_netif != NULL) {
532 if (loc_netif == netif) {
533 loc_netif = loc_netif->next;
534 continue;
535 }
536 if (IP_IS_V4_VAL(ifconfig_cmd->ip_addr) && ip_addr_cmp(&netif->netmask, &loc_netif->netmask) &&
537 ip_addr_netcmp_val(&loc_netif->ip_addr, &ip_addr, ip_2_ip4(&netif->netmask))) {
538 ERR_IFCONFIG_STRING_PUT(ret, "Duplicate network!\n");
539 goto out;
540 }
541 loc_netif = loc_netif->next;
542 }
543
544 #if LWIP_DHCP
545 if (netif_dhcp_data(netif) && netif_dhcp_data(netif)->state != DHCP_STATE_OFF) {
546 (void)netif_dhcp_off(netif);
547 }
548 #endif
549 netif_set_ipaddr(netif, ip_2_ip4(&ip_addr));
550 } else if (IP_IS_V6_VAL(ifconfig_cmd->ip_addr)) {
551 idx = -1;
552 err = netif_add_ip6_address(netif, ip_2_ip6(&ip_addr), &idx);
553 if (err != ERR_OK || idx == -1) {
554 ERR_IFCONFIG_STRING_PUT(ret, "The IPv6 has reached the Global address limit, "
555 "you should delete one address before add!\n");
556 goto out;
557 }
558 }
559 }
560
561 if (ifconfig_cmd->option & IFCONFIG_OPTION_DEL_IP) {
562 (void)netif_do_rmv_ipv6_addr(netif, &ifconfig_cmd->ip_addr);
563 }
564
565 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_NETMASK) {
566 ip_addr_set_val(&netmask, &(ifconfig_cmd->netmask));
567 /* check data valid */
568 if (!ip_addr_netmask_valid(ip_2_ip4(&netmask))) {
569 ERR_IFCONFIG_STRING_PUT(ret, "ifconfig: netmask is invalid!\n");
570 goto out;
571 }
572
573 #if LWIP_DHCP
574 if (netif_dhcp_data(netif) && netif_dhcp_data(netif)->state != DHCP_STATE_OFF) {
575 (void)netif_dhcp_off(netif);
576 }
577 #endif
578 if (netif_ip4_netmask(netif)->addr != ip_2_ip4(&netmask)->addr) {
579 /* lwip disallow two netif sit in same net at the same time */
580 loc_netif = netif_list;
581 while (loc_netif != NULL) {
582 if (loc_netif == netif) {
583 loc_netif = loc_netif->next;
584 continue;
585 }
586 if (ip_addr_cmp(&loc_netif->netmask, &netmask) &&
587 ip_addr_netcmp(&loc_netif->ip_addr, &netif->ip_addr, ip_2_ip4(&netmask))) {
588 ERR_IFCONFIG_STRING_PUT(ret, "Duplicate network!\n");
589 goto out;
590 }
591 loc_netif = loc_netif->next;
592 }
593 netif_set_netmask(netif, ip_2_ip4(&netmask));
594 /* check if gateway still reachable */
595 if (!ip_addr_netcmp(&netif->gw, &netif->ip_addr, ip_2_ip4(&netmask))) {
596 ip_addr_set_zero(&(netif->gw));
597 if (netif == netif_default) {
598 (void)netif_set_default(NULL);
599 }
600 }
601 }
602 }
603
604 if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_HW) &&
605 netif_set_hwaddr(netif, ifconfig_cmd->ethaddr, NETIF_MAX_HWADDR_LEN) != ERR_OK) {
606 ERR_IFCONFIG_STRING_PUT(ret, "Failed to update the hwaddr of the device!\n");
607 (void)netif_set_up(netif);
608 goto out;
609 }
610
611 if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) ||
612 (ifconfig_cmd->option & IFCONFIG_OPTION_SET_NETMASK) ||
613 (ifconfig_cmd->option & IFCONFIG_OPTION_SET_HW)) {
614 (void)netif_set_up(netif);
615 }
616
617 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_GW) {
618 ip_addr_set_val(&gw, &ifconfig_cmd->gw);
619
620 /* check the address multicast/0/loopback */
621 if (ip_addr_ismulticast_val(&gw) || ip_addr_isbroadcast_val(&gw, netif) ||
622 ip_addr_isany(&gw) || ip_addr_isloopback(&gw)) {
623 ERR_IFCONFIG_STRING_PUT(ret, "Don't set gateway as a multicast/broadcast/0/loopback address!\n");
624 goto out;
625 }
626
627 /* check if reachable */
628 if (!ip_addr_netcmp_val(&gw, &netif->ip_addr, ip_2_ip4(&netif->netmask))) {
629 ERR_IFCONFIG_STRING_PUT(ret, "The address is unreachable!\n");
630 goto out;
631 }
632
633 if (netif_default != netif) {
634 ip_addr_set_zero(&netif->gw);
635 (void)netif_set_default(netif);
636 }
637
638 #if LWIP_DHCP
639 if (netif_dhcp_data(netif) && netif_dhcp_data(netif)->state != DHCP_STATE_OFF) {
640 (void)netif_dhcp_off(netif);
641 }
642 #endif
643 netif_set_gw(netif, ip_2_ip4(&gw));
644 }
645
646 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_MTU) {
647 mtu = ifconfig_cmd->mtu;
648 if (netif_set_mtu(netif, mtu) != ERR_OK) {
649 ERR_IFCONFIG_STRING_PUT(ret, "Invalid MTU\n");
650 }
651 }
652 out:
653 sys_sem_signal(&ifconfig_cmd->cb_completed);
654 }
655
656
lwip_printsize(size_t size)657 void lwip_printsize(size_t size)
658 {
659 static const char *SIZES[] = {"B", "KB", "MB", "GB"};
660 size_t divis = 0;
661 size_t rem = 0;
662
663 while ((size >= 1024) && (divis < ((sizeof(SIZES) / sizeof(char *)) - 1))) {
664 rem = (size % 1024);
665 divis++;
666 size /= 1024;
667 }
668
669 PRINTK("(%.1f %s) \r\n", (float)size + (float)rem / 1024.0, SIZES[divis]);
670 }
671
lwip_ifconfig_usage(const char * cmd)672 LWIP_STATIC void lwip_ifconfig_usage(const char *cmd)
673 {
674 PRINTK("Usage:"\
675 "\n%s [-a] "\
676 "\n[interface]"\
677 "\n[interface ipaddr] <netmask mask> <gateway gw>"\
678 "\n[interface inet6 add|del ipaddr]"\
679 "\n[interface hw ether MAC]"\
680 "\n[interface mtu NN]"\
681 "\n[interface up|down]\n",
682 cmd);
683 }
684
lwip_ifconfig(int argc,const char ** argv)685 u32_t lwip_ifconfig(int argc, const char **argv)
686 {
687 int i;
688 static struct ifconfig_option ifconfig_cmd;
689 err_t ret;
690
691 #if LWIP_STATS
692 u32_t stat_err_cnt;
693 u32_t stat_drop_cnt;
694 u32_t stat_rx_or_tx_cnt;
695 u32_t stat_rx_or_tx_bytes;
696 #endif
697
698 #if LWIP_ARP
699 u32_t retval;
700 struct netif *netiftmp = NULL;
701 #if LWIP_ENABLE_IP_CONFLICT_SIGNAL
702 u32_t old_ip4addr;
703 err_t err;
704 extern sys_sem_t ip_conflict_detect;
705 extern u32_t is_ip_conflict_signal;
706 #endif /* LWIP_ENABLE_IP_CONFLICT_SIGNAL */
707 #endif /* LWIP_ARP */
708 #if LWIP_IPV6
709 extern sys_sem_t dup_addr_detect;
710 extern u32_t is_dup_detect_initialized;
711 #endif
712 if (!tcpip_init_finish) {
713 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__);
714 return 2;
715 }
716 /* To support "ifconfig -a" command
717 RX packets:XXXX errors:X dropped:X overruns:X bytes:XXXX (Human readable format)
718 TX packets:XXXX errors:X dropped:X overruns:X bytes:XXXX (Human readable format)
719
720 Below is assumed for 'overrun' stat.
721 Linux Kernel:
722 RX: FIFO overrun
723 Data structure: net_device->stats->rx_fifo_errors
724 Flag which is marked when FIFO overrun: ENRSR_FO
725
726 Function: ei_receive->ENRSR_FO
727
728 TX: A "FIFO underrun" occurred during transmit.
729 Data structure: net_device->stats->tx_fifo_errors
730 Flag which is marked when FIFO underrun: ENTSR_FU
731
732 Function: ei_tx_intr->ENTSR_FU
733
734 LWIP:
735 So in our case,
736 while receiving a packet RX case, if the buffer is full (trypost - it is sys_mbox_trypost)
737 the error will be returned, we can consider that an overflow has happened.
738 So this can be RX overrun.
739
740 But while transmitting a packet TX case, underrun cannot happen because it block on the
741 message Q if it is full (NOT trypost - it is sys_mbox_post). So TX overrun is always 0.
742 */
743 if (argc) {
744 if (strcmp("-a", argv[0]) == 0) {
745 #if LWIP_STATS
746 stat_rx_or_tx_cnt = lwip_stats.ip.recv;
747 stat_err_cnt = (u32_t)(lwip_stats.ip.ip_rx_err +
748 lwip_stats.ip.lenerr +
749 lwip_stats.ip.chkerr +
750 lwip_stats.ip.opterr +
751 lwip_stats.ip.proterr);
752 stat_drop_cnt = (u32_t)(lwip_stats.ip.drop + lwip_stats.link.link_rx_drop);
753 stat_rx_or_tx_bytes = lwip_stats.ip.ip_rx_bytes;
754
755 PRINTK("%18s:%u\t errors:%u\t ip dropped:%u\t link dropped:%u\t overrun:%d\t bytes:%u ",
756 "RX packets",
757 stat_rx_or_tx_cnt,
758 stat_err_cnt,
759 stat_drop_cnt,
760 lwip_stats.link.link_rx_drop,
761 lwip_stats.ip.link_rx_overrun,
762 stat_rx_or_tx_bytes);
763
764 /* Print in Human readable format of the incoming bytes */
765 lwip_printsize(lwip_stats.ip.ip_rx_bytes);
766 #if IP6_STATS
767 stat_rx_or_tx_cnt = lwip_stats.ip6.recv;
768 stat_err_cnt = (u32_t)(lwip_stats.ip6.ip_rx_err +
769 lwip_stats.ip6.lenerr +
770 lwip_stats.ip6.chkerr +
771 lwip_stats.ip6.opterr +
772 lwip_stats.ip6.proterr);
773 stat_drop_cnt = lwip_stats.ip6.drop;
774 stat_rx_or_tx_bytes = lwip_stats.ip6.ip_rx_bytes;
775
776 PRINTK("%18s:%u\t errors:%u\t dropped:%u\t overrun:%d\t bytes:%u ",
777 "RX packets(ip6)",
778 stat_rx_or_tx_cnt,
779 stat_err_cnt,
780 stat_drop_cnt,
781 lwip_stats.ip.link_rx_overrun,
782 stat_rx_or_tx_bytes);
783
784 /* Print in Human readable format of the incoming bytes */
785 lwip_printsize(lwip_stats.ip6.ip_rx_bytes);
786 #endif
787 stat_rx_or_tx_cnt = (u32_t)(lwip_stats.ip.fw + lwip_stats.ip.xmit);
788 stat_err_cnt = (u32_t)(lwip_stats.ip.rterr + lwip_stats.ip.ip_tx_err);
789 /* IP layer drop stat param is not maintained, failure at IP is considered in 'errors' stat */
790 stat_drop_cnt = lwip_stats.link.link_tx_drop;
791 stat_rx_or_tx_bytes = lwip_stats.ip.ip_tx_bytes;
792
793 PRINTK("%18s:%u\t errors:%u\t link dropped:%u\t overrun:0\t bytes:%u",
794 "TX packets",
795 stat_rx_or_tx_cnt,
796 stat_err_cnt,
797 stat_drop_cnt,
798 stat_rx_or_tx_bytes);
799
800 /* Print in Human readable format of the outgoing bytes */
801 lwip_printsize(lwip_stats.ip.ip_tx_bytes);
802
803 stat_rx_or_tx_cnt = (u32_t)(lwip_stats.ip6.fw + lwip_stats.ip6.xmit);
804 stat_err_cnt = (u32_t)(lwip_stats.ip6.rterr + lwip_stats.ip6.ip_tx_err);
805 stat_rx_or_tx_bytes = lwip_stats.ip6.ip_tx_bytes;
806
807 PRINTK("%18s:%u\t errors:%u\t overrun:0\t bytes:%u",
808 "TX packets(ip6)",
809 stat_rx_or_tx_cnt,
810 stat_err_cnt,
811 stat_rx_or_tx_bytes);
812
813 /* Print in Human readable format of the outgoing bytes */
814 lwip_printsize(lwip_stats.ip6.ip_tx_bytes);
815 #endif /* LWIP_STATS */
816 return 0;
817 }
818 }
819
820 (void)memset_s(&ifconfig_cmd, sizeof(ifconfig_cmd), 0, sizeof(ifconfig_cmd));
821 if (sys_sem_new(&ifconfig_cmd.cb_completed, 0) != ERR_OK) {
822 PRINTK("%s: sys_sem_new fail\n", __FUNCTION__);
823 return 1;
824 }
825
826 i = 0;
827 /* Get the interface */
828 if (argc > 0) {
829 if (strlen(argv[i]) < IFNAMSIZ) {
830 if (strncpy_s(ifconfig_cmd.iface, IFNAMSIZ, argv[i], (strlen(argv[i]))) != EOK) {
831 sys_sem_free(&ifconfig_cmd.cb_completed);
832 PRINTK("ifconfig : strncpy_s error\n");
833 return 1;
834 }
835 ifconfig_cmd.iface[IFNAMSIZ - 1] = '\0';
836 } else {
837 sys_sem_free(&ifconfig_cmd.cb_completed);
838 PRINTK("ifconfig : interface name is too big\n");
839 return 1;
840 }
841 i++;
842 argc--;
843 if (argc == 0) {
844 /* no more arguments, show the interface state. */
845 ret = tcpip_callback(lwip_ifconfig_show_internal, &ifconfig_cmd);
846 if (ret != ERR_OK) {
847 sys_sem_free(&ifconfig_cmd.cb_completed);
848 PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret);
849 return 1;
850 }
851 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0);
852 sys_sem_free(&ifconfig_cmd.cb_completed);
853 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
854 PRINTK("%s", ifconfig_cmd.cb_print_buf);
855 return 0;
856 }
857 } else {
858 /* no more arguments, show all the interface state. */
859 ret = tcpip_callback(lwip_ifconfig_show_internal, &ifconfig_cmd);
860 if (ret != ERR_OK) {
861 sys_sem_free(&ifconfig_cmd.cb_completed);
862 PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret);
863 return 1;
864 }
865 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0);
866 sys_sem_free(&ifconfig_cmd.cb_completed);
867 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
868 PRINTK("%s", ifconfig_cmd.cb_print_buf);
869
870 return 0;
871 }
872
873 /* ifup/ifdown */
874 if (strcmp("up", argv[i]) == 0) {
875 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_UP;
876 /* setup the interface, other arguments is ignored. */
877 ret = tcpip_callback(lwip_ifconfig_internal, &ifconfig_cmd);
878 if (ret != ERR_OK) {
879 sys_sem_free(&ifconfig_cmd.cb_completed);
880 PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret);
881 return 1;
882 }
883 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0);
884 sys_sem_free(&ifconfig_cmd.cb_completed);
885 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
886 PRINTK("%s", ifconfig_cmd.cb_print_buf);
887 return 0;
888 } else if (strcmp("down", argv[i]) == 0) {
889 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_DOWN;
890 /* setdown the interface, other arguments is ignored. */
891 ret = tcpip_callback(lwip_ifconfig_internal, &ifconfig_cmd);
892 if (ret != ERR_OK) {
893 sys_sem_free(&ifconfig_cmd.cb_completed);
894 PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret);
895 return 1;
896 }
897 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0);
898 sys_sem_free(&ifconfig_cmd.cb_completed);
899 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
900 PRINTK("%s", ifconfig_cmd.cb_print_buf);
901 return 0;
902 }
903 /* check if set the ip address. */
904 #if LWIP_ARP
905 netiftmp = netifapi_netif_find_by_name(ifconfig_cmd.iface);
906 if (netiftmp == NULL) {
907 sys_sem_free(&ifconfig_cmd.cb_completed);
908 PRINTK("ifconfig : Interface %s not found\n", ifconfig_cmd.iface);
909 return 1;
910 }
911 #if LWIP_ENABLE_IP_CONFLICT_SIGNAL
912 old_ip4addr = ipaddr_addr(ipaddr_ntoa(&netiftmp->ip_addr));
913 #endif /* LWIP_ENABLE_IP_CONFLICT_SIGNAL */
914 #endif /* LWIP_ARP */
915 if (!strcmp(argv[i], "inet") || ip4addr_aton(argv[i], ip_2_ip4(&ifconfig_cmd.ip_addr))) {
916 if (!strcmp(argv[i], "inet")) {
917 if (argc <= 1) {
918 sys_sem_free(&ifconfig_cmd.cb_completed);
919 goto ifconfig_error;
920 }
921
922 if (!ip4addr_aton(argv[i + 1], ip_2_ip4(&ifconfig_cmd.ip_addr))) {
923 sys_sem_free(&ifconfig_cmd.cb_completed);
924 PRINTK("ifconfig : Invalid IPv4 Address\n");
925 return 1;
926 }
927 argc--;
928 i++;
929 }
930 IP_SET_TYPE_VAL((ifconfig_cmd.ip_addr), IPADDR_TYPE_V4);
931 #if LWIP_ARP
932 if (!ip_addr_cmp(&ifconfig_cmd.ip_addr, &netiftmp->ip_addr)) {
933 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_IP;
934 }
935 #else
936 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_IP;
937 #endif /* LWIP_ARP */
938 argc--;
939 i++;
940 } else if (!strcmp(argv[i], "inet6")) {
941 if (argc < 3) {
942 sys_sem_free(&ifconfig_cmd.cb_completed);
943 goto ifconfig_error;
944 }
945 if (strcmp(argv[i + 1], "add") && strcmp(argv[i + 1], "del")) {
946 sys_sem_free(&ifconfig_cmd.cb_completed);
947 goto ifconfig_error;
948 }
949
950 if (!ip6addr_aton(argv[i + 2], ip_2_ip6(&ifconfig_cmd.ip_addr))) {
951 sys_sem_free(&ifconfig_cmd.cb_completed);
952 PRINTK("ifconfig : Invalid IPv6 Address\n");
953 return 1;
954 }
955
956 IP_SET_TYPE_VAL((ifconfig_cmd.ip_addr), IPADDR_TYPE_V6);
957 ifconfig_cmd.option |= (!strcmp(argv[i + 1], "add") ? IFCONFIG_OPTION_SET_IP : IFCONFIG_OPTION_DEL_IP);
958 argc -= 3;
959 i += 3;
960 }
961
962 if (ifconfig_cmd.option & IFCONFIG_OPTION_DEL_IP) {
963 if (argc != 0) {
964 sys_sem_free(&ifconfig_cmd.cb_completed);
965 goto ifconfig_error;
966 }
967 }
968
969 while (argc > 0) {
970 if (strcmp("netmask", argv[i]) == 0 && (argc > 1) && (ipaddr_addr(argv[i + 1]) != IPADDR_NONE)) {
971 /* if set netmask */
972 ip_addr_set_ip4_u32_val((ifconfig_cmd.netmask), ipaddr_addr(argv[i + 1]));
973 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_NETMASK;
974 i += 2;
975 argc -= 2;
976 } else if (strcmp("gateway", argv[i]) == 0 && (argc > 1) && (ipaddr_addr(argv[i + 1]) != IPADDR_NONE)) {
977 /* if set gateway */
978 ip_addr_set_ip4_u32_val((ifconfig_cmd.gw), ipaddr_addr(argv[i + 1]));
979 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_GW;
980 i += 2;
981 argc -= 2;
982 } else if (strcmp("hw", argv[i]) == 0 && argc > 2 && strcmp("ether", argv[i + 1]) == 0) {
983 /* if set HWaddr */
984 char *digit = NULL;
985 u32_t macaddrlen = strlen(argv[i + 2]) + 1;
986 char tmpStr[MAX_MACADDR_STRING_LENGTH];
987 char *tmpStr1 = NULL;
988 char *saveptr = NULL;
989 int j;
990
991 if (macaddrlen != MAX_MACADDR_STRING_LENGTH) {
992 sys_sem_free(&ifconfig_cmd.cb_completed);
993 PRINTK("ifconfig : wrong MAC address format\n");
994 return 1;
995 }
996
997 if (strncpy_s(tmpStr, MAX_MACADDR_STRING_LENGTH, argv[i + 2], macaddrlen - 1) != 0) {
998 sys_sem_free(&ifconfig_cmd.cb_completed);
999 PRINTK("ifconfig : wrong MAC address\n");
1000 return 1;
1001 }
1002 for (j = 0, tmpStr1 = tmpStr; j < 6; j++, tmpStr1 = NULL) {
1003 digit = strtok_r(tmpStr1, ":", &saveptr);
1004 if ((digit == NULL) || (strlen(digit) > 2)) {
1005 sys_sem_free(&ifconfig_cmd.cb_completed);
1006 PRINTK("ifconfig : wrong MAC address format\n");
1007 return 1;
1008 }
1009 CONVERT_STRING_TO_HEX(digit, ifconfig_cmd.ethaddr[j]);
1010 }
1011 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_HW;
1012 i += 3;
1013 argc -= 3;
1014 } else if (!strcmp("mtu", argv[i]) && (argc > 1)) {
1015 /* if set mtu */
1016 if ((atoi(argv[i + 1]) < 0) || (atoi(argv[i + 1]) > 0xFFFF)) {
1017 sys_sem_free(&ifconfig_cmd.cb_completed);
1018 PRINTK("\nifconfig: Invalid argument for mtu\n");
1019 goto ifconfig_error;
1020 }
1021
1022 ifconfig_cmd.mtu = (u16_t)(atoi(argv[i + 1]));
1023 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_MTU;
1024 i += 2;
1025 argc -= 2;
1026 } else {
1027 sys_sem_free(&ifconfig_cmd.cb_completed);
1028 goto ifconfig_error;
1029 }
1030 }
1031
1032 #if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL
1033 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V4_VAL((ifconfig_cmd.ip_addr))) {
1034 /* Create the semaphore for ip conflict detection. */
1035 if (sys_sem_new(&ip_conflict_detect, 0) != ERR_OK) {
1036 sys_sem_free(&ifconfig_cmd.cb_completed);
1037 PRINTK("ifconfig: internal error\n");
1038 return 1;
1039 }
1040 is_ip_conflict_signal = 1;
1041 }
1042 #endif /* LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL */
1043
1044 #if LWIP_IPV6
1045 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V6_VAL((ifconfig_cmd.ip_addr))) {
1046 /* Create the semaphore for duplicate address detection. */
1047 if (sys_sem_new(&dup_addr_detect, 0) != ERR_OK) {
1048 sys_sem_free(&ifconfig_cmd.cb_completed);
1049 PRINTK("ifconfig: internal error\n");
1050 return 1;
1051 }
1052 is_dup_detect_initialized = 1;
1053 }
1054 #endif /* LWIP_IPV6 */
1055
1056 ret = tcpip_callback(lwip_ifconfig_internal, &ifconfig_cmd);
1057 if (ret != ERR_OK) {
1058 sys_sem_free(&ifconfig_cmd.cb_completed);
1059 #if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL
1060 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V4_VAL((ifconfig_cmd.ip_addr))) {
1061 is_ip_conflict_signal = 0;
1062 sys_sem_free(&ip_conflict_detect);
1063 }
1064 #endif /* LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL */
1065
1066 #if LWIP_IPV6
1067 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V6_VAL((ifconfig_cmd.ip_addr))) {
1068 is_dup_detect_initialized = 0;
1069 sys_sem_free(&dup_addr_detect);
1070 }
1071 #endif /* LWIP_IPV6 */
1072
1073 PRINTK("%s : tcpip_callback failed in line %d : errnu %d", __FUNCTION__, __LINE__, ret);
1074 return 1;
1075 }
1076 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0);
1077 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
1078 PRINTK("%s", ifconfig_cmd.cb_print_buf);
1079 #if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL
1080 /* Pend 2 seconds for waiting the arp reply if the ip is already in use. */
1081 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V4_VAL((ifconfig_cmd.ip_addr))) {
1082 err = (err_t)sys_arch_sem_wait(&ip_conflict_detect, DUP_ARP_DETECT_TIME);
1083 is_ip_conflict_signal = 0;
1084 sys_sem_free(&ip_conflict_detect);
1085 if (err < 0) {
1086 /* The result neither conflict nor timeout. */
1087 PRINT_ERR("ifconfig: internal error\n");
1088 sys_sem_free(&ifconfig_cmd.cb_completed);
1089 return 1;
1090 } else if (err < DUP_ARP_DETECT_TIME) {
1091 /* Duplicate use of new ip, restore it to the old one. */
1092 PRINT_ERR("ifconfig: ip conflict!\n");
1093 ip_addr_set_ip4_u32_val(ifconfig_cmd.ip_addr, old_ip4addr);
1094 ret = tcpip_callback(lwip_ifconfig_internal, &ifconfig_cmd);
1095 if (ret != ERR_OK) {
1096 sys_sem_free(&ifconfig_cmd.cb_completed);
1097 PRINTK("%s : tcpip_callback failed in line %d : errnu %d", __FUNCTION__, __LINE__, ret);
1098 return 1;
1099 }
1100 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0);
1101 sys_sem_free(&ifconfig_cmd.cb_completed);
1102 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
1103 PRINTK("%s", ifconfig_cmd.cb_print_buf);
1104 return 1;
1105 }
1106 }
1107 #endif /* LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL */
1108 #if LWIP_IPV6
1109 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V6_VAL(ifconfig_cmd.ip_addr)) {
1110 /* Pend 2 seconds for waiting the arp reply if the ip is already in use. */
1111 retval = sys_arch_sem_wait(&dup_addr_detect, DUP_ARP_DETECT_TIME);
1112 is_dup_detect_initialized = 0;
1113 sys_sem_free(&dup_addr_detect);
1114 if (retval == SYS_ARCH_ERROR) {
1115 sys_sem_free(&ifconfig_cmd.cb_completed);
1116 /* The result neither conflict nor timeout. */
1117 PRINT_ERR("ifconfig: internal error\n");
1118 return 1;
1119 } else if (retval < DUP_ARP_DETECT_TIME) {
1120 /* Duplicate use of new ip, restore it to the old one. */
1121 struct netif *netif = NULL;
1122 PRINT_ERR("ifconfig: IP conflict!\n");
1123 netif = netifapi_netif_find_by_name(ifconfig_cmd.iface);
1124 i = netif_get_ip6_addr_match(netif, &ifconfig_cmd.ip_addr.u_addr.ip6);
1125 if (i >= 0) {
1126 netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
1127 }
1128
1129 sys_sem_free(&ifconfig_cmd.cb_completed);
1130 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
1131 PRINTK("%s", ifconfig_cmd.cb_print_buf);
1132 return 1;
1133 }
1134 }
1135 #endif /* LWIP_IPV6 */
1136 sys_sem_free(&ifconfig_cmd.cb_completed);
1137 return 0;
1138 ifconfig_error:
1139 lwip_ifconfig_usage("ifconfig");
1140 return 1;
1141 }
1142
1143 #ifdef LOSCFG_SHELL
1144 SHELLCMD_ENTRY(ifconfig_shellcmd, CMD_TYPE_EX, "ifconfig", XARGS, (CmdCallBackFunc)lwip_ifconfig);
1145 #endif /* LOSCFG_SHELL */
1146 /* add arp entry to arp cache */
1147 #define ARP_OPTION_ADD 1
1148 /* delete arp entry to arp cache */
1149 #define ARP_OPTION_DEL 2
1150 /* print all arp entry in arp cache */
1151 #define ARP_OPTION_SHOW 3
1152
1153 struct arp_option {
1154 /* see the ARP_OPTION_ above */
1155 int option;
1156 /* descriptive abbreviation of network interface */
1157 char iface[IFNAMSIZ];
1158 /* ip addr */
1159 unsigned int ipaddr;
1160 /* hw addr */
1161 unsigned char ethaddr[6];
1162 /* when using telnet, print to the telnet socket will result in system */
1163 /* deadlock.so don't do it. cache the data to print to a buf, and when */
1164 /* callback returns, then print the data out to the telnet socket */
1165 sys_sem_t cb_completed;
1166 char cb_print_buf[PRINT_BUF_LEN];
1167 int print_buf_len;
1168 };
1169
1170 #ifndef LWIP_TESTBED
1171 LWIP_STATIC
1172 #endif
lwip_arp_show_internal(struct netif * netif,char * printf_buf,unsigned int buf_len)1173 void lwip_arp_show_internal(struct netif *netif, char *printf_buf, unsigned int buf_len)
1174 {
1175 u8_t state, i;
1176 int ret;
1177 char *tmp = printf_buf;
1178 if (buf_len < 1) {
1179 return;
1180 }
1181 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%-24s%-24s%-12s%-12s\n", "Address", "HWaddress", "Iface", "Type");
1182 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
1183 return;
1184 tmp += ret;
1185 buf_len -= (unsigned int)ret;
1186
1187 if (netif != NULL) {
1188 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
1189 state = arp_table[i].state;
1190 if (((state == ETHARP_STATE_STABLE)
1191 #if ETHARP_SUPPORT_STATIC_ENTRIES
1192 || (state == ETHARP_STATE_STATIC)
1193 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
1194 ) && arp_table[i].netif) {
1195 if (strcmp(netif_get_name(netif), netif_get_name(arp_table[i].netif)) != 0) {
1196 continue;
1197 }
1198
1199 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%-24s%02X:%02X:%02X:%02X:%02X:%02X %s %s\n",
1200 ip4addr_ntoa(&arp_table[i].ipaddr),
1201 arp_table[i].ethaddr.addr[0], arp_table[i].ethaddr.addr[1],
1202 arp_table[i].ethaddr.addr[2], arp_table[i].ethaddr.addr[3],
1203 arp_table[i].ethaddr.addr[4], arp_table[i].ethaddr.addr[5],
1204 netif_get_name(netif),
1205 #if ETHARP_SUPPORT_STATIC_ENTRIES
1206 ((state == ETHARP_STATE_STATIC) ? "static" : "dynamic")
1207 #else
1208 "dynamic"
1209 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
1210 );
1211 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
1212 return;
1213 tmp += ret;
1214 buf_len -= (unsigned int)ret;
1215 }
1216 }
1217 } else {
1218 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
1219 state = arp_table[i].state;
1220 if (((state == ETHARP_STATE_STABLE)
1221 #if ETHARP_SUPPORT_STATIC_ENTRIES
1222 || (state == ETHARP_STATE_STATIC)
1223 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
1224 ) && arp_table[i].netif) {
1225 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%-24s%02X:%02X:%02X:%02X:%02X:%02X %s %s\n",
1226 ip4addr_ntoa(&arp_table[i].ipaddr),
1227 arp_table[i].ethaddr.addr[0], arp_table[i].ethaddr.addr[1],
1228 arp_table[i].ethaddr.addr[2], arp_table[i].ethaddr.addr[3],
1229 arp_table[i].ethaddr.addr[4], arp_table[i].ethaddr.addr[5],
1230 netif_get_name(arp_table[i].netif),
1231 #if ETHARP_SUPPORT_STATIC_ENTRIES
1232 ((state == ETHARP_STATE_STATIC) ? "static" : "dynamic")
1233 #else
1234 "dynamic"
1235 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
1236 );
1237 if ((ret <= 0) || ((unsigned int)ret >= buf_len))
1238 return;
1239 tmp += ret;
1240 buf_len -= (unsigned int)ret;
1241 }
1242 }
1243 }
1244 }
1245
1246 #ifndef LWIP_TESTBED
1247 LWIP_STATIC
1248 #endif
lwip_arp_internal(void * arg)1249 void lwip_arp_internal(void *arg)
1250 {
1251 #if LWIP_IPV4
1252 struct arp_option *arp_cmd = (struct arp_option *)arg;
1253 struct netif *netif = NULL;
1254 struct eth_addr ethaddr;
1255 ip4_addr_t ipaddr;
1256 err_t ret = 0;
1257 int type = 0;
1258
1259 if (arp_cmd->iface[0] == 'd' && arp_cmd->iface[1] == 'e') {
1260 netif = NULL;
1261 } else {
1262 /* find the specified netif by it's name */
1263 netif = netif_find(arp_cmd->iface);
1264 if (netif == NULL) {
1265 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "No such device\n");
1266 goto out;
1267 }
1268 }
1269
1270 type = arp_cmd->option;
1271 switch (type) {
1272 case ARP_OPTION_SHOW:
1273 if (netif != NULL) {
1274 lwip_arp_show_internal(netif, arp_cmd->cb_print_buf, PRINT_BUF_LEN);
1275 } else {
1276 lwip_arp_show_internal(NULL, arp_cmd->cb_print_buf, PRINT_BUF_LEN);
1277 }
1278 break;
1279
1280 case ARP_OPTION_ADD:
1281 #if ETHARP_SUPPORT_STATIC_ENTRIES
1282 ipaddr.addr = arp_cmd->ipaddr;
1283 (void)memcpy_s(ethaddr.addr, sizeof(ethaddr.addr), arp_cmd->ethaddr, 6);
1284 if (netif != NULL) {
1285 if (ip4_addr_netcmp(&ipaddr, ip_2_ip4(&(netif->ip_addr)), ip_2_ip4(&(netif->netmask)))) {
1286 ret = etharp_update_arp_entry(netif, &ipaddr, ðaddr,
1287 ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
1288 } else {
1289 ret = ERR_RTE;
1290 }
1291 } else {
1292 ret = etharp_add_static_entry(&ipaddr, ðaddr);
1293 }
1294 #else
1295 ret = ERR_ARG;
1296 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
1297 break;
1298
1299 case ARP_OPTION_DEL:
1300 ipaddr.addr = arp_cmd->ipaddr;
1301 (void)memcpy_s(ethaddr.addr, sizeof(ethaddr.addr), arp_cmd->ethaddr, 6);
1302 if (netif != NULL) {
1303 ret = etharp_delete_arp_entry(netif, &ipaddr);
1304 } else {
1305 for (netif = netif_list; netif != NULL; netif = netif->next) {
1306 ret = etharp_delete_arp_entry(netif, &ipaddr);
1307 if (ret == ERR_OK) {
1308 /* only can del success one time */
1309 break;
1310 }
1311 }
1312 }
1313 break;
1314
1315 default:
1316 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Error\n");
1317 goto out;
1318 }
1319
1320 out:
1321 if (type == ARP_OPTION_ADD || type == ARP_OPTION_DEL) {
1322 if (ret == ERR_MEM) {
1323 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Out of memory error\n");
1324 } else if (ret == ERR_ARG) {
1325 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Illegal argument\n");
1326 } else if (ret == ERR_RTE) {
1327 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Network is unreachable\n");
1328 } else {
1329 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Succeeded\n");
1330 }
1331 }
1332 #endif
1333
1334 sys_sem_signal(&arp_cmd->cb_completed);
1335 }
1336
1337
lwip_arp_usage(const char * cmd)1338 LWIP_STATIC void lwip_arp_usage(const char *cmd)
1339 {
1340 PRINTK("Usage:"
1341 "\n%s"
1342 "\n%s [-i IF] -s IPADDR HWADDR"
1343 "\n%s [-i IF] -d IPADDR\n",
1344 cmd, cmd, cmd);
1345 }
1346
lwip_arp(int argc,const char ** argv)1347 u32_t lwip_arp(int argc, const char **argv)
1348 {
1349 int i;
1350 struct arp_option arp_cmd;
1351 err_t ret;
1352 size_t interface_len = 0;
1353
1354 (void)memset_s(&arp_cmd, sizeof(struct arp_option), 0, sizeof(struct arp_option));
1355 if (!tcpip_init_finish) {
1356 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__);
1357 return LOS_NOK;
1358 }
1359
1360 arp_cmd.iface[0] = 'd';
1361 arp_cmd.iface[1] = 'e';
1362 arp_cmd.iface[2] = '0';
1363 arp_cmd.option = ARP_OPTION_SHOW;
1364 arp_cmd.print_buf_len = 0;
1365 if (sys_sem_new(&arp_cmd.cb_completed, 0) != ERR_OK) {
1366 PRINTK("%s: sys_sem_new fail\n", __FUNCTION__);
1367 return 1;
1368 }
1369
1370 i = 0;
1371 while (argc > 0) {
1372 if (strcmp("-i", argv[i]) == 0 && (argc > 1)) {
1373 /* get the network interface's name */
1374 interface_len = strlen(argv[i + 1]);
1375 if (interface_len < IFNAMSIZ) {
1376 if (strncmp(argv[i + 1], "lo", (sizeof("lo") - 1)) == 0) {
1377 PRINTK("Illegal operation\n");
1378 goto arp_error;
1379 }
1380 if (strncpy_s(arp_cmd.iface, IFNAMSIZ, argv[i + 1], interface_len) != EOK) {
1381 PRINTK("strncpy_s error\n");
1382 goto arp_error;
1383 }
1384 arp_cmd.iface[interface_len] = '\0';
1385 } else {
1386 PRINTK("Iface name is big \n");
1387 goto arp_error;
1388 }
1389 i += 2;
1390 argc -= 2; // 2: number of used parameters
1391 } else if (strcmp("-d", argv[i]) == 0 && (argc > 1)) {
1392 /* arp delete */
1393 arp_cmd.option = ARP_OPTION_DEL;
1394 arp_cmd.ipaddr = inet_addr(argv[i + 1]);
1395
1396 if (arp_cmd.ipaddr == IPADDR_NONE) {
1397 PRINTK("IP address is not correct!\n");
1398 goto arp_error;
1399 }
1400
1401 i += 2;
1402 argc -= 2; // 2: number of used parameters
1403 } else if (strcmp("-s", argv[i]) == 0 && (argc > 2)) { // 2: require more than 2 parameters
1404 /* arp add */
1405 char *digit = NULL;
1406 u32_t macaddrlen = strlen(argv[i + 2]) + 1;
1407 char tmpStr[MAX_MACADDR_STRING_LENGTH];
1408 char *tmpStr1 = NULL;
1409 char *saveptr1 = NULL;
1410 char *temp = NULL;
1411 int j;
1412
1413 arp_cmd.option = ARP_OPTION_ADD;
1414 arp_cmd.ipaddr = inet_addr(argv[i + 1]);
1415
1416 if (arp_cmd.ipaddr == IPADDR_NONE) {
1417 PRINTK("IP address is not correct!\n");
1418 goto arp_error;
1419 }
1420
1421 /* cannot add an arp entry of 127.*.*.* */
1422 if ((arp_cmd.ipaddr & (u32_t)0x0000007fUL) == (u32_t)0x0000007fUL) {
1423 PRINTK("IP address is not correct!\n");
1424 goto arp_error;
1425 }
1426
1427 if (macaddrlen != MAX_MACADDR_STRING_LENGTH) {
1428 PRINTK("Wrong MAC address length\n");
1429 goto arp_error;
1430 }
1431
1432 if (strncpy_s(tmpStr, MAX_MACADDR_STRING_LENGTH, argv[i + 2], macaddrlen - 1) != 0) {
1433 PRINTK("Wrong MAC address\n");
1434 goto arp_error;
1435 }
1436
1437 for (j = 0, tmpStr1 = tmpStr; j < 6; j++, tmpStr1 = NULL) {
1438 digit = strtok_r(tmpStr1, ":", &saveptr1);
1439 if ((digit == NULL) || (strlen(digit) > 2)) {
1440 PRINTK("MAC address is not correct\n");
1441 goto arp_error;
1442 }
1443
1444 for (temp = digit; *temp != '\0'; temp++) {
1445 if (!isxdigit(*temp)) {
1446 PRINTK("MAC address is not correct\n");
1447 goto arp_error;
1448 }
1449 }
1450
1451 CONVERT_STRING_TO_HEX(digit, arp_cmd.ethaddr[j]);
1452 }
1453
1454 i += 3;
1455 argc -= 3; // 3: number of used parameters
1456 } else {
1457 goto arp_error;
1458 }
1459 }
1460
1461 ret = tcpip_callback(lwip_arp_internal, &arp_cmd);
1462 if (ret != ERR_OK) {
1463 PRINTK("%s : tcpip_callback failed in line %d : errnu %d", __FUNCTION__, __LINE__, ret);
1464 sys_sem_free(&arp_cmd.cb_completed);
1465 return 1;
1466 }
1467 (void)sys_arch_sem_wait(&arp_cmd.cb_completed, 0);
1468 sys_sem_free(&arp_cmd.cb_completed);
1469 arp_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
1470 PRINTK("%s", arp_cmd.cb_print_buf);
1471 return 0;
1472
1473 arp_error:
1474 lwip_arp_usage("arp");
1475 sys_sem_free(&arp_cmd.cb_completed);
1476 return 1;
1477 }
1478
1479 #ifdef LOSCFG_SHELL_CMD_DEBUG
1480 SHELLCMD_ENTRY(arp_shellcmd, CMD_TYPE_EX, "arp", 1, (CmdCallBackFunc)lwip_arp);
1481 #endif /* LOSCFG_SHELL_CMD_DEBUG */
1482
ifup_internal(void * arg)1483 void ifup_internal(void *arg)
1484 {
1485 struct netif *netif = NULL;
1486 struct if_cmd_data *ifcmd_data;
1487
1488 ifcmd_data = (struct if_cmd_data *)arg;
1489 if (ifcmd_data == NULL) {
1490 return;
1491 }
1492 netif = netif_find(ifcmd_data->if_name);
1493 if (netif == NULL) {
1494 ifcmd_data->err = ERR_VAL;
1495 } else {
1496 (void)netif_set_up(netif);
1497 ifcmd_data->err = ERR_OK;
1498 }
1499
1500 sys_sem_signal(&ifcmd_data->cb_completed);
1501 }
1502
ifdown_internal(void * arg)1503 void ifdown_internal(void *arg)
1504 {
1505 struct netif *netif = NULL;
1506 struct if_cmd_data *ifcmd_data = NULL;
1507
1508 ifcmd_data = (struct if_cmd_data *)arg;
1509 if (ifcmd_data == NULL) {
1510 return;
1511 }
1512 netif = netif_find(ifcmd_data->if_name);
1513 if (netif == NULL) {
1514 ifcmd_data->err = ERR_VAL;
1515 } else {
1516 (void)netif_set_down(netif);
1517 ifcmd_data->err = ERR_OK;
1518 }
1519
1520 sys_sem_signal(&ifcmd_data->cb_completed);
1521 }
1522
1523 #if LWIP_DNS
1524 #ifndef LWIP_TESTBED
1525 LWIP_STATIC
1526 #endif
gethostnameinfo(const char * host)1527 struct hostent *gethostnameinfo(const char *host)
1528 {
1529 static struct hostent hostbuf;
1530 struct hostent *hp = NULL;
1531 const size_t hstbuflen = 1024;
1532 char tmphstbuf[1024];
1533 int res;
1534 int herr;
1535
1536 res = lwip_gethostbyname_r(host, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr);
1537 /* Check for errors. */
1538 if (res || hp == NULL)
1539 return NULL;
1540 return hp;
1541 }
1542
get_hostip(const char * hname)1543 LWIP_STATIC unsigned int get_hostip(const char *hname)
1544 {
1545 unsigned int ip = 0;
1546 int ret;
1547
1548 struct hostent *pent = gethostnameinfo(hname);
1549 if (pent == NULL || pent->h_addr == NULL)
1550 return 0;
1551 ret = memcpy_s(&ip, sizeof(ip), pent->h_addr, 4);
1552 if (ret != 0) {
1553 return 0;
1554 }
1555 return ip;
1556 }
1557 #endif
1558
1559 #if LWIP_EXT_POLL_SUPPORT
1560 static int ping_taskid = -1;
1561 static int ping_kill = 0;
1562 #define PING_ZERO_DATA_LEN 8
lwip_ping_usage(void)1563 static void lwip_ping_usage(void)
1564 {
1565 PRINTK("Usage:"\
1566 "\n ping"
1567 "\n ping [-n cnt] [-w interval] [-l data_len] destination"
1568 "\n ping [-t] [-w interval] destination"
1569 "\n ping -k");
1570 PRINTK("\n -t means ping forever, user can use -k to stop the forever ping\n");
1571 }
1572
osPingFunc(u32_t destip,u32_t cnt,u32_t interval,u32_t data_len)1573 LWIP_STATIC int osPingFunc(u32_t destip, u32_t cnt, u32_t interval, u32_t data_len)
1574 {
1575 int sfd;
1576 struct sockaddr_in to;
1577 struct pbuf *pbuf_resp = NULL;
1578 struct icmp_echo_hdr *iecho = NULL;
1579 struct icmp_echo_hdr *iecho_resp = NULL;
1580 struct ip_hdr *iphdr_resp = NULL;
1581 u32_t iecho_len;
1582 s16_t ip_hlen;
1583 u32_t forever;
1584 u32_t i = 0;
1585 u32_t succ_cnt = 0;
1586 u32_t failed_cnt = 0;
1587 struct timespec start, end;
1588 long timout_ms = 0;
1589 struct pollfd pfd;
1590 long rtt;
1591 int ret = 0;
1592 u32_t intrvl = 0;
1593 char *data_buf = NULL;
1594 BOOL timeout_flag = false;
1595 char buf[50];
1596
1597 iecho_len = sizeof(struct icmp_echo_hdr) + data_len;
1598 sfd = lwip_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
1599 if (sfd < 0) {
1600 perror("Ping socket");
1601 return -1;
1602 }
1603 pbuf_resp = pbuf_alloc(PBUF_RAW, IP_HLEN + sizeof(struct icmp_echo_hdr), PBUF_RAM);
1604 if (pbuf_resp == NULL) {
1605 PRINTK("Ping: pbuf_resp malloc failed\n");
1606 ret = -1;
1607 goto FAILURE;
1608 }
1609 iecho = (struct icmp_echo_hdr *)mem_malloc(iecho_len);
1610 if (iecho == NULL) {
1611 PRINTK("Ping: echo request malloc failed\n");
1612 ret = -1;
1613 goto FAILURE;
1614 }
1615
1616 to.sin_family = AF_INET;
1617 to.sin_addr.s_addr = destip; /* already in network order */
1618 to.sin_port = 0;
1619
1620 if (data_len > PING_ZERO_DATA_LEN) {
1621 (void)memset_s(iecho, sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN,
1622 0, sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN);
1623 data_buf = (char *)iecho + sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN;
1624 for (i = 0; i < data_len - PING_ZERO_DATA_LEN; i++) {
1625 *(data_buf + i) = i + 0x10;
1626 }
1627 } else {
1628 (void)memset_s(iecho, sizeof(struct icmp_echo_hdr) + data_len, 0, sizeof(struct icmp_echo_hdr) + data_len);
1629 }
1630 iecho->id = htons((u16_t)LOS_CurTaskIDGet());
1631 ICMPH_TYPE_SET(iecho, (u8_t)ICMP_ECHO);
1632 forever = (cnt ? 0 : 1);
1633 i = 0;
1634 while (!ping_kill && (forever || (i < cnt))) {
1635 iecho->seqno = htons((u16_t)i);
1636 iecho->chksum = 0;
1637 iecho->chksum = inet_chksum((void *)iecho, iecho_len);
1638
1639 ret = sendto(sfd, iecho, iecho_len, 0, (struct sockaddr *)&to, (socklen_t)sizeof(to));
1640 if (ret < 0) {
1641 perror("Ping: sending ICMP echo request failed\n");
1642 goto FAILURE;
1643 }
1644
1645 /* capture the start time to calculate RTT */
1646 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &start);
1647
1648 /* poll for ICMP echo response msg */
1649 pfd.fd = sfd;
1650
1651 do {
1652 pfd.events = POLLIN;
1653 pfd.revents = 0;
1654 timeout_flag = false;
1655 ret = poll(&pfd, 1, LWIP_SHELL_CMD_PING_TIMEOUT);
1656 if (ret < 0) {
1657 perror("Ping: poll\n");
1658 goto FAILURE;
1659 } else if (ret == 0) {
1660 /* first type timeout event */
1661 timeout_flag = true;
1662 break;
1663 }
1664
1665 ret = recv(sfd, pbuf_resp->payload, pbuf_resp->len, MSG_DONTWAIT);
1666 if (ret < 0) {
1667 perror("Ping: recv echo reply failed\n");
1668 goto FAILURE;
1669 }
1670
1671 /* Accessing ip header and icmp header */
1672 iphdr_resp = pbuf_resp->payload;
1673
1674 ip_hlen = (IPH_HL(iphdr_resp) << 2);
1675 if (pbuf_header(pbuf_resp, -ip_hlen)) {
1676 /* this failure will never happen, but failure handle is written just to be in safe side */
1677 PRINTK("Ping : memory management failure\n");
1678 goto FAILURE;
1679 }
1680 iecho_resp = (struct icmp_echo_hdr *)pbuf_resp->payload;
1681 /* Reverting back pbuf to its original state */
1682 if (pbuf_header(pbuf_resp, ip_hlen)) {
1683 /* this failure will never happen, but failure handle is written just to be in safe side */
1684 PRINTK("ping : memory management failure\n");
1685 goto FAILURE;
1686 }
1687
1688 if ((iphdr_resp->src.addr != to.sin_addr.s_addr) ||
1689 ((ICMPH_TYPE(iecho_resp) == ICMP_ECHO) && (iphdr_resp->src.addr == to.sin_addr.s_addr))) {
1690 /* second type timeout event */
1691 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end);
1692 timout_ms = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000);
1693 timout_ms = LWIP_SHELL_CMD_PING_TIMEOUT - timout_ms;
1694 } else {
1695 timout_ms = 0;
1696 break;
1697 }
1698 } while (timout_ms >= 0);
1699
1700 /* all timeout events are true timeout */
1701 if ((timout_ms < 0) || (timeout_flag == true)) {
1702 failed_cnt++;
1703 i++;
1704 PRINTK("\nPing: destination unreachable ...");
1705 continue;
1706 }
1707 /* capture the end time to calculate round trip time */
1708 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end);
1709 rtt = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000);
1710
1711 if (iphdr_resp->src.addr == to.sin_addr.s_addr) {
1712 switch (ICMPH_TYPE(iecho_resp)) {
1713 case ICMP_ER:
1714 PRINTK("\n[%u]Reply from %s: ", i, inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf)));
1715 if (rtt > 0) {
1716 PRINTK("time=%ims ", rtt);
1717 } else {
1718 PRINTK("time<1ms ");
1719 }
1720 PRINTK("TTL=%u", iphdr_resp->_ttl);
1721
1722 /* delay 1s for every successful ping */
1723 intrvl = interval;
1724 do {
1725 if (intrvl < 1000) {
1726 sys_msleep(intrvl);
1727 break;
1728 }
1729 intrvl -= 1000;
1730 sys_msleep(1000); // 1000: delay 1 s
1731 if (ping_kill == 1)
1732 break;
1733 } while (intrvl > 0);
1734 succ_cnt++;
1735 break;
1736 case ICMP_DUR:
1737 PRINTK("\nPing: destination host unreachable ...");
1738 break;
1739 case ICMP_SQ:
1740 PRINTK("\nPing: source quench ...");
1741 break;
1742 case ICMP_RD:
1743 PRINTK("\nPing: redirect ...");
1744 break;
1745 case ICMP_TE:
1746 PRINTK("\nPing: time exceeded ...");
1747 break;
1748 case ICMP_PP:
1749 PRINTK("\nPing: parameter problem ...");
1750 break;
1751 default :
1752 PRINTK("\nPing: unknown error ...");
1753 break;
1754 }
1755 i++;
1756 }
1757 }
1758
1759 PRINTK("\n--- %s ping statistics ---\n", inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf)));
1760 PRINTK("%u packets transmitted, %u received, %u loss\n", i, succ_cnt, failed_cnt);
1761
1762 FAILURE:
1763 ping_kill = 0;
1764 (void)lwip_close(sfd);
1765 if (pbuf_resp != NULL) {
1766 (void)pbuf_free(pbuf_resp);
1767 }
1768 if (iecho != NULL) {
1769 mem_free(iecho);
1770 }
1771 return ret;
1772 }
1773
ping_cmd(unsigned int p0,unsigned int p1,unsigned int p2,unsigned int p3)1774 static void ping_cmd(unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3)
1775 {
1776 u32_t destip = p0;
1777 u32_t count = p1;
1778 u32_t interval = p2;
1779 u32_t data_len = p3;
1780 int ret;
1781
1782 ret = osPingFunc(destip, count, interval, data_len);
1783 if (ret < 0) {
1784 PRINTK("Ping cmd failed due to some errors\n");
1785 }
1786
1787 ping_taskid = -1;
1788 }
1789
osShellPing(int argc,const char ** argv)1790 u32_t osShellPing(int argc, const char **argv)
1791 {
1792 int ret;
1793 u32_t i = 0;
1794 u32_t count = 0;
1795 int count_set = 0;
1796 u32_t interval = 1000; /* default ping interval */
1797 u32_t data_len = 48; /* default data length */
1798 ip4_addr_t dst_ipaddr;
1799 TSK_INIT_PARAM_S stPingTask;
1800
1801 if (!tcpip_init_finish) {
1802 PRINTK("Ping: tcpip_init have not been called\n");
1803 return LOS_NOK;
1804 }
1805
1806 if ((argc < 1) || (argv == NULL)) {
1807 PRINTK("Ping: require dest ipaddr at least\n");
1808 goto ping_error;
1809 }
1810
1811 /* could add more param support */
1812 while (argc > 0) {
1813 if (strcmp("-n", argv[i]) == 0 && (argc > 1)) {
1814 ret = atoi(argv[i + 1]);
1815 if (ret <= 0) {
1816 PRINTK("Ping count should be greater than 0 \n");
1817 goto ping_error;
1818 }
1819 count = ret;
1820 count_set = 1;
1821 i += 2;
1822 argc -= 2; // 2: nuber of arguments that has been checked
1823 } else if (strcmp("-t", argv[i]) == 0) {
1824 count = 0; /* ping forerver */
1825 count_set = 1;
1826 i++;
1827 argc--;
1828 } else if (strcmp("-w", argv[i]) == 0 && (argc > 1)) {
1829 ret = atoi(argv[i + 1]);
1830 if (ret <= 0) {
1831 PRINTK("Ping interval should be greater than 0 \n");
1832 goto ping_error;
1833 }
1834
1835 interval = ret;
1836 i += 2;
1837 argc -= 2; // 2:number of arguments that has been checked
1838 } else if (strcmp("-l", argv[i]) == 0 && (argc > 1)) {
1839 ret = atoi(argv[i + 1]);
1840 if (ret < 0 || ret > (int)(LWIP_MAX_UDP_RAW_SEND_SIZE - sizeof(struct icmp_echo_hdr))) {
1841 PRINTK("Ping data length error, should be in range of [0, %d] \n",
1842 LWIP_MAX_UDP_RAW_SEND_SIZE - sizeof(struct icmp_echo_hdr));
1843 goto ping_error;
1844 }
1845 data_len = ret;
1846 i += 2;
1847 argc -= 2; // 2: number of elements has been checked
1848 } else if (strcmp("-k", argv[i]) == 0) {
1849 if (ping_taskid > 0) {
1850 ping_kill = 1; /* stop the current ping task */
1851 return LOS_OK;
1852 } else {
1853 PRINTK("No ping task running...\n");
1854 return LOS_NOK;
1855 }
1856 } else {
1857 if (argc == 1) {
1858 break;
1859 } else {
1860 PRINTK("Invalid Ping param\n");
1861 goto ping_error;
1862 }
1863 }
1864 }
1865
1866 if (!count_set) {
1867 count = LWIP_SHELL_CMD_PING_RETRY_TIMES;
1868 }
1869
1870 /* initialize dst IP address */
1871 if (argc <= 0) {
1872 goto ping_error;
1873 }
1874 #if LWIP_DNS
1875 dst_ipaddr.addr = get_hostip(argv[i]);
1876 #else /* LWIP_DNS */
1877 dst_ipaddr.addr = inet_addr(argv[i]);
1878 #endif /* LWIP_DNS */
1879
1880 if (dst_ipaddr.addr == IPADDR_NONE || dst_ipaddr.addr == IPADDR_ANY) {
1881 PRINTK("Invalid dest ipaddr: NONE or ANY\n");
1882 return LOS_NOK;
1883 }
1884
1885 /* start one task if ping forever or ping count greater than 60 */
1886 if (count == 0 || count > LWIP_SHELL_CMD_PING_RETRY_TIMES) {
1887 if (ping_taskid > 0) {
1888 PRINTK("Ping task already running and only support one now\n");
1889 return LOS_NOK;
1890 }
1891 stPingTask.pfnTaskEntry = (TSK_ENTRY_FUNC)ping_cmd;
1892 stPingTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
1893 stPingTask.pcName = "ping_task";
1894 stPingTask.usTaskPrio = 8; /* higher than shell */
1895 stPingTask.uwResved = LOS_TASK_STATUS_DETACHED;
1896 stPingTask.auwArgs[0] = dst_ipaddr.addr; /* network order */
1897 stPingTask.auwArgs[1] = count;
1898 stPingTask.auwArgs[2] = interval;
1899 stPingTask.auwArgs[3] = data_len; // 3: index of data length
1900 ret = LOS_TaskCreate((UINT32 *)(&ping_taskid), &stPingTask);
1901 if (ret != LOS_OK) {
1902 PRINTK("ping_task create failed 0x%08x.\n", ret);
1903 count = LWIP_SHELL_CMD_PING_RETRY_TIMES;
1904 } else {
1905 return LOS_OK;
1906 }
1907 }
1908
1909 /* two cases:
1910 1, ping cout less than LWIP_SHELL_CMD_PING_RETRY_TIMES;
1911 2, ping task create failed;
1912 */
1913 if (osPingFunc(dst_ipaddr.addr, count, interval, data_len) < 0) {
1914 PRINTK("Ping cmd failed due some errors\n");
1915 }
1916
1917 return LOS_OK;
1918 ping_error:
1919 lwip_ping_usage();
1920 return LOS_NOK;
1921 }
1922 #ifdef LOSCFG_SHELL
1923 SHELLCMD_ENTRY(ping_shellcmd, CMD_TYPE_EX, "ping", XARGS, (CmdCallBackFunc)osShellPing);
1924 #endif /* LOSCFG_SHELL */
1925
1926 #else /* LWIP_EXT_POLL_SUPPORT */
1927
osShellPing(int argc,const char ** argv)1928 u32_t osShellPing(int argc, const char **argv)
1929 {
1930 int sfd;
1931 struct sockaddr_in to;
1932 struct icmp_echo_hdr iecho;
1933 struct pbuf *pbuf_resp = NULL;
1934 struct icmp_echo_hdr *iecho_resp = NULL;
1935 struct ip_hdr *iphdr_resp = NULL;
1936 s16_t ip_hlen;
1937 ip_addr_t dst_ipaddr;
1938 fd_set fdReadSet;
1939 struct timeval stTimeVal;
1940 struct timespec start, end;
1941 int ret;
1942 s32_t i;
1943 long rtt;
1944 s32_t pingcount;
1945 char buf[50];
1946
1947 if (!tcpip_init_finish) {
1948 PRINTK("ping: tcpip_init have not been called\n");
1949 return LOS_NOK;
1950 }
1951
1952 if ((argc < 1) || (argv == NULL)) {
1953 PRINTK("ping : invalid arguments, ping command receives ip as command line argument \n");
1954 return LOS_NOK;
1955 }
1956
1957 if (argc == 2) {
1958 pingcount = atoi(argv[1]);
1959 if (pingcount < 1)
1960 pingcount = LWIP_SHELL_CMD_PING_RETRY_TIMES;
1961 } else {
1962 pingcount = LWIP_SHELL_CMD_PING_RETRY_TIMES;
1963 }
1964 PRINTK("ping %u packets start.\n", pingcount);
1965
1966 /* initialize dst IP address */
1967 #if LWIP_DNS
1968 ip_2_ip4(&dst_ipaddr)->addr = get_hostip(argv[0]);
1969 #else /* LWIP_DNS */
1970 ip_2_ip4(&dst_ipaddr)->addr = inet_addr(argv[0]);
1971 #endif /* LWIP_DNS */
1972
1973 to.sin_family = AF_INET;
1974 to.sin_addr.s_addr = ip_2_ip4(&dst_ipaddr)->addr;
1975 to.sin_port = 0;
1976
1977 if (to.sin_addr.s_addr == IPADDR_NONE || to.sin_addr.s_addr == IPADDR_ANY) {
1978 PRINTK("ping : invalid ip address : NONE or ANY\n");
1979 return LOS_NOK;
1980 }
1981
1982 sfd = lwip_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
1983 if (sfd == -1) {
1984 PRINTK("ping : failed, socket creation failed\n");
1985 return LOS_NOK;
1986 }
1987
1988 pbuf_resp = pbuf_alloc(PBUF_RAW, IP_HLEN + sizeof(struct icmp_echo_hdr), PBUF_RAM);
1989 if (pbuf_resp == NULL) {
1990 PRINTK("ping : memory allocation failed\n");
1991 goto FAILURE;
1992 }
1993
1994 for (i = 0; i < pingcount; i++) {
1995 (void)memset_s(&iecho, sizeof(iecho), 0, sizeof(iecho));
1996 ICMPH_TYPE_SET(&iecho, (u8_t)ICMP_ECHO);
1997 iecho.chksum = inet_chksum(&iecho, sizeof(struct icmp_echo_hdr));
1998
1999 ret = lwip_sendto(sfd, &iecho, sizeof(struct icmp_echo_hdr), 0, (struct sockaddr *)&to, (socklen_t)sizeof(to));
2000 if (ret == -1) {
2001 PRINTK("ping : sending ICMP echo msg failed\n");
2002 goto FAILURE;
2003 }
2004
2005 /* capture the start time to calculate round trip time */
2006 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &start);
2007 /* Wait in select for ICMP response msg */
2008 FD_ZERO(&fdReadSet);
2009 FD_SET(sfd, &fdReadSet);
2010 stTimeVal.tv_sec = LWIP_SHELL_CMD_PING_TIMEOUT / 1000;
2011 stTimeVal.tv_usec = 0;
2012
2013 DO_SELECT:
2014 ret = select(sfd + 1, &fdReadSet, 0, 0, &stTimeVal);
2015 if (ret < 0) {
2016 PRINTK("ping : select failure\n");
2017 goto FAILURE;
2018 } else if (ret == 0) {
2019 PRINTK("Request timed out.\n");
2020 continue;
2021 }
2022
2023 /* capture the end time to calculate round trip time */
2024 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end);
2025 rtt = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000);
2026
2027 ret = lwip_recv(sfd, pbuf_resp->payload, pbuf_resp->len, 0);
2028 if (ret == -1) {
2029 PRINTK("ping : receiving ICMP echo response msg failed\n");
2030 goto FAILURE;
2031 }
2032
2033 /* Accessing ip header and icmp header */
2034 iphdr_resp = (struct ip_hdr *)(pbuf_resp->payload);
2035 ip_hlen = (s16_t)(IPH_HL(iphdr_resp) * 4);
2036 if (pbuf_header(pbuf_resp, (s16_t)(-ip_hlen))) {
2037 /* this failure will never happen, but failure handle is written just to be in safe side */
2038 PRINTK("ping : memory management failure\n");
2039 goto FAILURE;
2040 }
2041 iecho_resp = (struct icmp_echo_hdr *)pbuf_resp->payload;
2042
2043 /* Reverting back pbuf to its original state */
2044 if (pbuf_header(pbuf_resp, ip_hlen)) {
2045 /* this failure will never happen, but failure handle is written just to be in safe side */
2046 PRINTK("ping : memory management failure\n");
2047 goto FAILURE;
2048 }
2049
2050 if (iphdr_resp->src.addr == to.sin_addr.s_addr) {
2051 if (ICMPH_TYPE(iecho_resp) == ICMP_ER) {
2052 PRINTK("[%u]Reply from %s: time=%ims TTL=%u\n", i,
2053 inet_ntoa_r(to.sin_addr.s_addr, buf, sizeof(buf)), rtt, iphdr_resp->_ttl);
2054 } else if (ICMPH_TYPE(iecho_resp) == ICMP_ECHO) {
2055 /* If ping self, stack will receive a ICMP_ECHO request message flowing a ICMP_ER reply message,
2056 and we need reply only, do select again */
2057 goto DO_SELECT;
2058 }
2059 }
2060 }
2061
2062 (void)lwip_close(sfd);
2063 (void)pbuf_free(pbuf_resp);
2064 return LOS_OK;
2065
2066 FAILURE:
2067 (void)lwip_close(sfd);
2068 if (pbuf_resp != NULL) {
2069 (void)pbuf_free(pbuf_resp);
2070 }
2071
2072 return LOS_NOK;
2073 }
2074
2075 #ifdef LOSCFG_SHELL
2076 SHELLCMD_ENTRY(ping_shellcmd, CMD_TYPE_EX, "ping", XARGS, (CmdCallBackFunc)osShellPing);
2077 #endif /* LOSCFG_SHELL */
2078
2079 #endif /* LWIP_EXT_POLL_SUPPORT */
2080
2081 #if LWIP_IPV6
osShellPing6(int argc,const char ** argv)2082 u32_t osShellPing6(int argc, const char **argv)
2083 {
2084 u16_t icmpv6_id;
2085 u16_t icmpv6_seq;
2086 u32_t nsent;
2087 u32_t nrecieve;
2088 u32_t last_received;
2089 struct timespec start, end, start_in_reply;
2090 struct timespec first, last;
2091 long rtt;
2092 int ret;
2093 fd_set fdReadSet;
2094 void *param = NULL;
2095 ping6_args_t ping6_params;
2096 ping6_stats_t ping6_stats;
2097 struct sockaddr_in6 to;
2098 struct icmp6_echo_hdr *iecho_resp = NULL;
2099 struct icmp6_echo_hdr *iecho = NULL;
2100 struct timeval stTimeVal;
2101 struct timeval deltaTimeVal;
2102 struct pbuf *pbuf_resp = NULL;
2103 struct pbuf *pbuf_req = NULL;
2104 int sfd = -1;
2105 u8_t type;
2106 u8_t select_on_socket = 0;
2107 char buf[INET6_ADDRSTRLEN];
2108
2109 if (!tcpip_init_finish) {
2110 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__);
2111 ret = -1;
2112 goto exit;
2113 }
2114
2115 if ((argc < 1) || (argc > LWIP_MAX_PING6_ARG_COUNT) || (argv == NULL)) {
2116 goto usage;
2117 }
2118
2119 ret = parse_args_ping6(argc, argv, &ping6_params);
2120 if (ret == -1) {
2121 goto exit;
2122 }
2123
2124 if (ping6_params.args_found & LWIP_PING6_SOURCE_ADDRESS_ARG) {
2125 type = LWIP_PING6_SOURCE_ADDRESS_ARG;
2126 param = (void *)(&ping6_params.src_addr);
2127 } else if (ping6_params.args_found & LWIP_PING6_INTERFACE_ARG) {
2128 type = LWIP_PING6_INTERFACE_ARG;
2129 param = (void *)(argv[ping6_params.interface_index]);
2130 } else {
2131 type = LWIP_PING6_DEFAULT_SOCKET;
2132 param = NULL;
2133 }
2134
2135 /* Create a socket for sending and receiving pings with appropriate bindings */
2136 sfd = create_ping6_socket(type, param);
2137 if (sfd == -1) {
2138 ret = -1;
2139 goto exit;
2140 }
2141
2142 pbuf_req = pbuf_alloc(PBUF_RAW, LWIP_PING6_STANDARD_PKT_SIZE, PBUF_RAM);
2143 pbuf_resp = pbuf_alloc(PBUF_RAW, LWIP_PING6_STANDARD_PKT_SIZE, PBUF_RAM);
2144 if ((pbuf_resp == NULL) || (pbuf_req == NULL)) {
2145 PRINTK("ping6 : Memory Allocation Failed\n");
2146 ret = -1;
2147 goto exit;
2148 }
2149
2150 to.sin6_family = AF_INET6;
2151 inet6_addr_from_ip6addr(&to.sin6_addr, &(ping6_params.dst_addr));
2152 to.sin6_port = htons(IPPROTO_ICMPV6);
2153
2154 #if LWIP_DNS
2155 if (lwip_strnicmp(inet_ntop(AF_INET6, &to.sin6_addr, buf, sizeof(buf)), argv[ping6_params.host_index],
2156 sizeof(to.sin6_addr))) {
2157 /* If There Was A DNS Resolution */
2158 PRINTK("PING %s (%s) with %d bytes of data.\n",
2159 argv[ping6_params.host_index], buf, LWIP_PING6_STANDARD_PKT_SIZE);
2160 } else {
2161 PRINTK("PING %s with %d bytes of data.\n", buf, LWIP_PING6_STANDARD_PKT_SIZE);
2162 }
2163 #else
2164 PRINTK("PING %s with %d bytes of data\n", inet_ntop(AF_INET6, &to.sin6_addr, buf, sizeof(buf)), LWIP_PING6_STANDARD_PKT_SIZE);
2165 #endif /* LWIP_DNS */
2166
2167 nrecieve = 0;
2168 ping6_stats.flag = 0;
2169 ping6_stats.avg_rtt = 0;
2170 ping6_stats.max_rtt = 0;
2171 ping6_stats.min_rtt = 0;
2172 last_received = LWIP_PING6_STARTING_SEQ_NUM + LWIP_PING6_OUT_OF_ORDER_MAGNITUDE + 1;
2173 icmpv6_id = (u16_t)LWIP_RAND();
2174 icmpv6_seq = LWIP_PING6_STARTING_SEQ_NUM;
2175 /* Setting the start time of the entire ping task for statistics */
2176 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &first);
2177
2178 for (nsent = 0; nsent < ping6_params.pingcount; nsent++) {
2179 /* capture the start tick to calculate rtt */
2180 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &start);
2181 /* Initialize Memory To Prevent Uninitialized Memory Read Write Issues */
2182 if (memset_s(pbuf_req->payload, pbuf_req->len, (int)(start.tv_nsec), pbuf_req->len) != 0) {
2183 goto exit;
2184 }
2185
2186 iecho = (struct icmp6_echo_hdr *)pbuf_req->payload;
2187 iecho->type = ICMP6_TYPE_EREQ;
2188 iecho->id = icmpv6_id;
2189 icmpv6_seq++;
2190 iecho->seqno = icmpv6_seq;
2191 iecho->code = 0;
2192
2193 /* Embedding the start_tick as data into the icmp_payload */
2194 (void)pbuf_header(pbuf_req, (s16_t)(-(s16_t)(sizeof(struct icmp6_echo_hdr))));
2195 if (memcpy_s(pbuf_req->payload, pbuf_req->len, (void *)&start, sizeof(start)) != 0) {
2196 goto exit;
2197 }
2198 (void)pbuf_header(pbuf_req, (s16_t)((s16_t)(sizeof(struct icmp6_echo_hdr))));
2199
2200 ret = lwip_sendto(sfd, iecho, pbuf_req->len, 0, (struct sockaddr *)&to, (socklen_t)sizeof(to));
2201 if (ret == -1) {
2202 PRINTK("ping6 : Sending ICMP Echo message failed\n");
2203 goto exit;
2204 }
2205
2206 /* Wait in select for ICMP response msg */
2207 FD_ZERO(&fdReadSet);
2208 FD_SET(sfd, &fdReadSet);
2209 stTimeVal.tv_sec = LWIP_MSECS_TO_SECS(LWIP_SHELL_CMD_PING_TIMEOUT);
2210 stTimeVal.tv_usec = 0;
2211 select_on_socket = 1;
2212
2213 while (select_on_socket) {
2214 select_on_socket = 0;
2215 ret = select(sfd + 1, &fdReadSet, 0, 0, &stTimeVal);
2216 if (ret < 0) {
2217 PRINTK("ping6 : select failure\n");
2218 goto exit;
2219 } else if (ret == 0) {
2220 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end);
2221 PRINTK("Request timed out\n");
2222 continue;
2223 }
2224
2225 /* capture the end time to calculate round trip time */
2226 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end);
2227
2228 ret = lwip_recv(sfd, pbuf_resp->payload, pbuf_resp->len, 0);
2229 if (ret == -1) {
2230 PRINTK("ping6 : receiving ICMP echo response msg failed\n");
2231 goto exit;
2232 }
2233
2234 if ((u32_t)ret < sizeof(struct icmp6_echo_hdr *)) {
2235 /* Drop the packet if its too short [Doesn't contain even the header !!] */
2236 PRINTK("ping6 : received ICMP echo response too short\n");
2237 goto REDUCE_SELECT_TIME;
2238 }
2239
2240 /* Acceping the ICMPv6 payload. */
2241 /* Here, pbuf_resp->payload won't contain IPv6 Header since its an AF_INET6 RAW Socket */
2242 iecho_resp = (struct icmp6_echo_hdr *)pbuf_resp->payload;
2243
2244 if (iecho_resp->id == icmpv6_id) {
2245 if (iecho_resp->type == ICMP6_TYPE_EREP) {
2246 if (ret < LWIP_PING6_STANDARD_PKT_SIZE) {
2247 /* Drop the packet if its too short */
2248 PRINTK("ping6 : received ICMP echo response too short\n");
2249 goto REDUCE_SELECT_TIME;
2250 }
2251 /* Accept and process only those delayed EREP only if its sequence num is within out-of-order magnitude */
2252 if (nsent && iecho_resp->seqno != icmpv6_seq &&
2253 (iecho_resp->seqno<(u16_t)(last_received - LWIP_PING6_OUT_OF_ORDER_MAGNITUDE) ||
2254 iecho_resp->seqno>(u16_t)(
2255 last_received + LWIP_PING6_OUT_OF_ORDER_MAGNITUDE))) {
2256 /* Otherwise drop it and wait for more packets */
2257 goto REDUCE_SELECT_TIME;
2258 }
2259 ++nrecieve;
2260 last_received = iecho_resp->seqno;
2261 /* Retrieving the start_tick from the packet which was embedded when the request was transmitted */
2262 (void)pbuf_header(pbuf_resp, (s16_t)(-(s16_t)(sizeof(struct icmp6_echo_hdr))));
2263 if (memcpy_s((void *)&start_in_reply, sizeof(start_in_reply),
2264 pbuf_resp->payload, sizeof(start_in_reply)) != EOK) {
2265 goto REDUCE_SELECT_TIME;
2266 }
2267 (void)pbuf_header(pbuf_resp, (s16_t)((s16_t)(sizeof(struct icmp6_echo_hdr))));
2268
2269 rtt = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000);
2270
2271 PRINTK("%d bytes from %s : icmp_seq=%d time", ret,
2272 inet_ntop(AF_INET6, &to.sin6_addr, buf, sizeof(buf)),
2273 ((iecho_resp->seqno) - LWIP_PING6_STARTING_SEQ_NUM));
2274 if (rtt < 1) {
2275 PRINTK("<1 ms\n");
2276 } else {
2277 PRINTK("=%i ms\n", rtt);
2278 }
2279
2280 update_ping6_stats(&ping6_stats, (u32_t)(rtt), nrecieve);
2281
2282 /* Checking if its a delayed packet */
2283 if ((iecho_resp->seqno != icmpv6_seq) && (nsent < ping6_params.pingcount)) {
2284 /* In case of delayed packet wait on socket for other response before sending a new PING */
2285 /* We have to reduce the timeout value now when selecting on socket */
2286 goto REDUCE_SELECT_TIME;
2287 }
2288 } else {
2289 PRINTK("[%u]ping6 : %s\n", nsent, convert_icmpv6_err_to_string(iecho_resp->type));
2290 }
2291 } else {
2292 /* If incoming packet does not matches with icmp_id, it should be ignored */
2293 /* Reduce the timeout for select on socket */
2294 REDUCE_SELECT_TIME:
2295 deltaTimeVal.tv_sec = (long)(end.tv_sec - start.tv_sec);
2296 deltaTimeVal.tv_usec = (long)((end.tv_nsec - start.tv_nsec) / 1000);
2297 /* Subtract deltaTime from stTime and store in stTime */
2298 /* This will reduce the select time on the socket */
2299 timersub(&stTimeVal, &deltaTimeVal, &stTimeVal);
2300 select_on_socket = 1;
2301 }
2302 }
2303 }
2304
2305 ret = ERR_OK;
2306
2307 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &last);
2308 /* Display ping stats */
2309 PRINTK("--- %s ping statistics ---\n", argv[ping6_params.host_index]);
2310 PRINTK("%d packets transmitted, %d received, %.2f%% packet loss, time %dms\n",
2311 nsent, nrecieve, (float)(((float)(nsent - nrecieve)) * ((float)(100)) / ((float)(nsent))),
2312 /* 1000: convert seconds to milliseconds, 1000000: convert nanoseconds to milliseconds */
2313 ((last.tv_sec - first.tv_sec) * 1000 + (last.tv_nsec - first.tv_nsec) / 1000000));
2314 if (nrecieve) {
2315 /* Display rtt stats only if at least one packet is received */
2316 PRINTK("rtt min/avg/max = %u/%.2f/%u ms\n", ping6_stats.min_rtt, ping6_stats.avg_rtt, ping6_stats.max_rtt);
2317 }
2318
2319 exit:
2320 if (sfd != -1) {
2321 (void)lwip_close(sfd);
2322 }
2323
2324 if (pbuf_resp != NULL) {
2325 (void)pbuf_free(pbuf_resp);
2326 }
2327
2328 if (pbuf_req != NULL) {
2329 (void)pbuf_free(pbuf_req);
2330 }
2331 return (u32_t)((ret == (int)ERR_OK) ? LOS_OK : LOS_NOK);
2332
2333 usage:
2334 PRINTK("Usage:\n");
2335 PRINTK("\tping6 [-c count] [-I interface/sourceAddress] destination\n");
2336 return LOS_NOK;
2337 }
2338
create_ping6_socket(u8_t type,const void * param)2339 LWIP_STATIC int create_ping6_socket(u8_t type, const void *param)
2340 {
2341 int sfd;
2342 int ret;
2343 struct sockaddr_in6 stHostAddr6;
2344 struct icmp6_filter icmp6_sock_filter;
2345
2346 sfd = lwip_socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
2347 if (sfd == -1) {
2348 PRINTK("ping6 : Failed, socket creation failed\n");
2349 return -1;
2350 }
2351
2352 if (param != NULL) {
2353 if (type == LWIP_PING6_SOURCE_ADDRESS_ARG) {
2354 /* Binding socket to the provided source address */
2355 (void)memset_s(&stHostAddr6, sizeof(stHostAddr6), 0, sizeof(stHostAddr6));
2356 stHostAddr6.sin6_family = AF_INET6;
2357 inet6_addr_from_ip6addr(&stHostAddr6.sin6_addr, (ip6_addr_t *)param);
2358 stHostAddr6.sin6_port = htons(IPPROTO_ICMPV6);
2359 stHostAddr6.sin6_scope_id = 0;
2360
2361 ret = lwip_bind(sfd, (struct sockaddr *)&stHostAddr6, sizeof(stHostAddr6));
2362 if (ret == -1) {
2363 (void)lwip_close(sfd);
2364 PRINTK("ping6 : bind icmp socket: cannot assign requested address\n");
2365 return ret;
2366 }
2367 } else if (type == LWIP_PING6_INTERFACE_ARG) {
2368 /* Binding socket to the provided netif */
2369 ret = lwip_setsockopt(sfd, SOL_SOCKET, SO_BINDTODEVICE, (char *)(param), strlen((char *)(param)));
2370 if (ret == -1) {
2371 (void)lwip_close(sfd);
2372 PRINTK("ping6: unknownn iface %s\n", (char *)(param));
2373 return ret;
2374 }
2375 }
2376 }
2377
2378 /* Setting socket filter since we are interested only in ECHO REPLY and ERROR messages */
2379 ICMP6_FILTER_SETBLOCKALL(&icmp6_sock_filter);
2380 ICMP6_FILTER_SETPASS(ICMP6_TYPE_EREP, &icmp6_sock_filter);
2381 ICMP6_FILTER_SETPASS(ICMP6_TYPE_DUR, &icmp6_sock_filter);
2382 ICMP6_FILTER_SETPASS(ICMP6_TYPE_PTB, &icmp6_sock_filter);
2383 ICMP6_FILTER_SETPASS(ICMP6_TYPE_TE, &icmp6_sock_filter);
2384
2385 ret = lwip_setsockopt(sfd, IPPROTO_ICMPV6, ICMP6_FILTER, &icmp6_sock_filter, sizeof(struct icmp6_filter));
2386 if (ret == -1) {
2387 (void)lwip_close(sfd);
2388 PRINTK("ping6 : setsockopt: Invalid Argument\n");
2389 return -1;
2390 }
2391
2392 return sfd;
2393 }
2394
2395 /*
2396 * Function to parse the command line args for ping6 shell utility
2397 * @return:
2398 * Success: ERR_OK
2399 * Failure: -1
2400 */
parse_args_ping6(int argc,const char ** argv,ping6_args_t * ping6_params)2401 LWIP_STATIC int parse_args_ping6(int argc, const char **argv, ping6_args_t *ping6_params)
2402 {
2403 int pingcount;
2404 int ret = -1;
2405 #if LWIP_DNS
2406 struct addrinfo *res = NULL;
2407 struct addrinfo hints_structure;
2408 #endif
2409 u8_t i = 0;
2410
2411 IP6_ADDR(&(ping6_params->dst_addr), 0, 0, 0, 0);
2412 IP6_ADDR(&(ping6_params->src_addr), 0, 0, 0, 0);
2413
2414 ping6_params->pingcount = LWIP_SHELL_CMD_PING_RETRY_TIMES;
2415 ping6_params->host_index = 0;
2416 ping6_params->args_found = 0;
2417
2418 while (i < argc) {
2419 if (strcmp("-c", argv[i]) == 0) {
2420 /* Handle number of ICMP packets to transmit :: -c [number_of_packets] */
2421 if (ping6_params->args_found & LWIP_PING6_COUNT_ARG) {
2422 PRINTK("ping6: -c option present multiple times \n");
2423 ret = -1;
2424 goto exit;
2425 }
2426
2427 if (i + 2 > argc) {
2428 PRINTK("ping6: ping count(-c) should require an argument \n");
2429 ret = -1;
2430 goto exit;
2431 }
2432
2433 pingcount = atoi(argv[i + 1]);
2434 if (pingcount <= 0) {
2435 PRINTK("ping6: bad number of packets to transmit \n");
2436 ret = -1;
2437 goto exit;
2438 }
2439
2440 ping6_params->args_found |= LWIP_PING6_COUNT_ARG;
2441 ping6_params->pingcount = (u32_t)pingcount;
2442 i = (u8_t)(i + 2);
2443 } else if (strcmp("-I", argv[i]) == 0) {
2444 /* Handle interface ID / sourceAddress using which the ICMP Packets has to be transmitted :: -I [interface_id/source_address] */
2445
2446 if ((ping6_params->args_found & LWIP_PING6_SOURCE_ADDRESS_ARG) ||
2447 (ping6_params->args_found & LWIP_PING6_INTERFACE_ARG)) {
2448 PRINTK("ping6: -I option present multiple times \n");
2449 ret = -1;
2450 goto exit;
2451 }
2452
2453 if (i + 2 > argc) {
2454 PRINTK("ping6: interface/source address(-I) should require an argument \n");
2455 ret = -1;
2456 goto exit;
2457 }
2458
2459 /* Check whether the given argument to -I is source address */
2460 if (ip6addr_aton(argv[i + 1], &(ping6_params->src_addr))) {
2461 ping6_params->args_found |= LWIP_PING6_SOURCE_ADDRESS_ARG;
2462 i = (u8_t)(i + 2);
2463 continue;
2464 }
2465
2466 /* Storing the index where interface name is found */
2467 /* If this name is not valid, then it will fail later in setsockopt(BIND_TO_DEVICE) */
2468 ping6_params->interface_index = (u8_t)(i + 1);
2469 ping6_params->args_found |= LWIP_PING6_INTERFACE_ARG;
2470
2471 i = (u8_t)(i + 2);
2472 } else {
2473 if (argv[i][0] == '-') {
2474 /* Check whether its a bad option */
2475 PRINTK("ping6: bad option %s\n", argv[i]);
2476 ret = -1;
2477 goto exit;
2478 } else if (ping6_params->args_found & LWIP_PING6_HOSTNAME_ARG) {
2479 /* Check whether hostname is already found and there are extra arguments */
2480 PRINTK("ping6: bad parameter %s\n", argv[i]);
2481 ret = -1;
2482 goto exit;
2483 }
2484
2485 #if LWIP_DNS
2486 /* Resolve the given hostname */
2487 hints_structure.ai_family = AF_INET6;
2488 hints_structure.ai_flags = 0;
2489 ret = lwip_getaddrinfo(argv[i], NULL, &hints_structure, &res);
2490 if (ret != ERR_OK) {
2491 PRINTK("ping6 : Host : %s can't be resolved to IPv6 address\n", argv[i]);
2492 ret = -1;
2493 goto exit;
2494 }
2495
2496 inet6_addr_to_ip6addr(&(ping6_params->dst_addr),
2497 &(((const struct sockaddr_in6 *)(res->ai_addr))->sin6_addr));
2498 #else
2499 /* Convert the string representation to network form */
2500 if (!ip6addr_aton(argv[i], &(ping6_params->dst_addr))) {
2501 PRINTK("ping6 : Invalid IPv6 Address : %s\n", argv[i]);
2502 ret = -1;
2503 goto exit;
2504 }
2505 #endif /* LWIP_DNS */
2506 if (ip6_addr_isany(&(ping6_params->dst_addr)) || ip6_addr_isnone(&(ping6_params->dst_addr))) {
2507 #if LWIP_DNS
2508 PRINTK("ping6 : IPv6 address of host : %s (%s) is invalid\n", argv[i],
2509 ip6addr_ntoa((const ip6_addr_t *)&(ping6_params->dst_addr)));
2510 #else
2511 PRINTK("ping6 : Invalid IPv6 address : %s\n", argv[i]);
2512 #endif /* LWIP_DNS */
2513 goto exit;
2514 }
2515 /* Setting host_index to the index of argv[] where the host/IP is present */
2516 ping6_params->args_found |= LWIP_PING6_HOSTNAME_ARG;
2517 ping6_params->host_index = (u8_t)(i);
2518 i = (u8_t)(i + 1);
2519 }
2520 }
2521
2522 if (!(ping6_params->args_found & LWIP_PING6_HOSTNAME_ARG)) {
2523 /* Hostname/IPv6 address not found */
2524 PRINTK("ping6 : Hostname/IPv6 address to ping is not specified\n");
2525 ret = -1;
2526 goto exit;
2527 }
2528
2529 if (ip6_addr_islinklocal(&(ping6_params->dst_addr)) &&
2530 !(ping6_params->args_found & (LWIP_PING6_INTERFACE_ARG | LWIP_PING6_SOURCE_ADDRESS_ARG))) {
2531 /* For link-local addresses, -I is mandatory */
2532 PRINTK("ping6 : Interface specification is mandatory for link-local addresses\n");
2533 ret = -1;
2534 goto exit;
2535 }
2536
2537 ret = ERR_OK;
2538
2539 exit:
2540 #if LWIP_DNS
2541 lwip_freeaddrinfo(res);
2542 #endif /* LWIP_DNS */
2543
2544 return ret;
2545 }
2546
2547 /*
2548 * Function to update ping6_stats
2549 * stats is maintained in ping6_stats structure
2550 */
update_ping6_stats(ping6_stats_t * ping6_stats,u32_t rtt,u32_t nreceived)2551 LWIP_STATIC void update_ping6_stats(ping6_stats_t *ping6_stats, u32_t rtt, u32_t nreceived)
2552 {
2553 if (rtt > ping6_stats->max_rtt) {
2554 ping6_stats->max_rtt = rtt;
2555 }
2556
2557 if (ping6_stats->flag == 0 || rtt < ping6_stats->min_rtt) {
2558 ping6_stats->min_rtt = rtt;
2559 ping6_stats->flag = 1;
2560 }
2561
2562 ping6_stats->avg_rtt = (float)(ping6_stats->avg_rtt +
2563 (float)((float)((float)rtt - ping6_stats->avg_rtt) / (float)(nreceived)));
2564 }
2565
convert_icmpv6_err_to_string(u8_t err_type)2566 LWIP_STATIC const char *convert_icmpv6_err_to_string(u8_t err_type)
2567 {
2568 switch (err_type) {
2569 case ICMP6_TYPE_DUR:
2570 return "Destination Unreachable";
2571 case ICMP6_TYPE_PTB:
2572 return "Packet too big";
2573 case ICMP6_TYPE_TE:
2574 return "Time Exceeded";
2575 case ICMP6_TYPE_PP:
2576 return "Parameter Problem";
2577 default:
2578 break;
2579 }
2580 return "Unknown Error";
2581 }
2582
2583 #ifdef LOSCFG_SHELL_CMD_DEBUG
2584 SHELLCMD_ENTRY(ping6_shellcmd, CMD_TYPE_EX, "ping6", XARGS, (CmdCallBackFunc)osShellPing6);
2585 #endif /* LOSCFG_SHELL_CMD_DEBUG */
2586 #endif /* LWIP_IPV6 */
2587
2588 #if LWIP_SNTP
osShellNtpdate(int argc,const char ** argv)2589 u32_t osShellNtpdate(int argc, const char **argv)
2590 {
2591 int server_num = 0;
2592 char *ret = NULL;
2593 struct timeval get_time;
2594 char buf[50];
2595
2596 (void)memset_s(&get_time, sizeof(struct timeval), 0, sizeof(struct timeval));
2597
2598 if (!tcpip_init_finish) {
2599 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__);
2600 return LOS_NOK;
2601 }
2602
2603 if (argc < 1 || argv == NULL) {
2604 goto usage;
2605 }
2606
2607 server_num = lwip_sntp_start(argc, (char **)argv, &get_time);
2608 if (server_num >= 0 && server_num < argc) {
2609 ret = ctime_r((time_t *)&get_time.tv_sec, buf);
2610 if (ret != NULL) {
2611 PRINTK("time server %s: %s\n", argv[server_num], ret);
2612 } else {
2613 PRINTK("ctime return null error\n");
2614 }
2615 } else {
2616 PRINTK("no server suitable for synchronization found\n");
2617 }
2618
2619 return LOS_OK;
2620
2621 usage:
2622 PRINTK("\nUsage:\n");
2623 PRINTK("ntpdate [SERVER_IP1] [SERVER_IP2] ...\n");
2624 return LOS_NOK;
2625 }
2626
2627 #ifdef LOSCFG_SHELL_CMD_DEBUG
2628 SHELLCMD_ENTRY(ntpdate_shellcmd, CMD_TYPE_EX, "ntpdate", XARGS, (CmdCallBackFunc)osShellNtpdate);
2629 #endif /* LOSCFG_SHELL_CMD_DEBUG */
2630
2631 #endif /* LWIP_SNTP */
2632
2633 #if LWIP_DNS
osShellDns(int argc,const char ** argv)2634 u32_t osShellDns(int argc, const char **argv)
2635 {
2636 ip_addr_t dns = {0};
2637 err_t err;
2638 int i;
2639 if (argc < 1 || argv == NULL) {
2640 goto usage;
2641 }
2642
2643 if (tcpip_init_finish == 0) {
2644 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__);
2645 return LOS_NOK;
2646 }
2647
2648 if (argc == 1 && (strcmp(argv[0], "-a") == 0)) {
2649 for (i = 0; i < DNS_MAX_SERVERS; i++) {
2650 err = lwip_dns_getserver((u8_t)i, &dns);
2651 if (err == ERR_OK) {
2652 PRINTK("dns %d: %s\n", i + 1, ipaddr_ntoa_unsafe(&dns));
2653 } else {
2654 PRINTK("dns: failed\n");
2655 return LOS_NOK;
2656 }
2657 }
2658 return LOS_OK;
2659 } else if (argc == 2) {
2660 i = atoi(argv[0]);
2661 if ((i <= 0) || (i > DNS_MAX_SERVERS))
2662 goto usage;
2663 #if LWIP_IPV6
2664 if (ip6addr_aton(argv[1], ((ip6_addr_t *)&dns))) {
2665 #if LWIP_IPV4 && LWIP_IPV6
2666 dns.type = IPADDR_TYPE_V6;
2667 #endif
2668 if (!ip6_addr_isglobal((ip6_addr_t *)&dns)) {
2669 PRINTK("ip address<%s> is wrong\n", argv[1]);
2670 return LOS_NOK;
2671 }
2672 } else
2673 #endif
2674 {
2675 #if LWIP_IPV4
2676 ((ip4_addr_t *)&dns)->addr = ipaddr_addr(argv[1]);
2677 if (((ip4_addr_t *)&dns)->addr == IPADDR_NONE) {
2678 PRINTK("ip address<%s> is wrong\n", argv[1]);
2679 return LOS_NOK;
2680 }
2681 #if LWIP_IPV4 && LWIP_IPV6
2682 dns.type = IPADDR_TYPE_V4;
2683 #endif
2684 #endif
2685 }
2686
2687 err = lwip_dns_setserver((u8_t)(i - 1), &dns);
2688 if (err != ERR_OK) {
2689 PRINTK("dns : failed\n");
2690 return LOS_NOK;
2691 }
2692 return LOS_OK;
2693 }
2694 usage:
2695 PRINTK("usage:\n");
2696 PRINTK("\tdns <1-%d> <IP>\n", DNS_MAX_SERVERS);
2697 PRINTK("\tdns -a\n");
2698 return LOS_NOK;
2699 }
2700
2701 #ifdef LOSCFG_SHELL_CMD_DEBUG
2702 SHELLCMD_ENTRY(dns_shellcmd, CMD_TYPE_EX, "dns", XARGS, (CmdCallBackFunc)osShellDns);
2703 #endif /* LOSCFG_SHELL_CMD_DEBUG */
2704 #endif /* LWIP_DNS */
2705 #if LWIP_IPV6
2706 extern struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS];
2707 #endif
2708 #if LWIP_IPV6
netstat_get_udp_sendQLen6(struct udp_pcb * udppcb,struct pbuf * udpbuf)2709 int netstat_get_udp_sendQLen6(struct udp_pcb *udppcb, struct pbuf *udpbuf)
2710 {
2711 int sendLen = -1;
2712 u16_t offset = 0, len;
2713 struct ip6_hdr *iphdr = NULL;
2714 struct udp_hdr *udphdr = NULL;
2715 struct ip6_dest_hdr *dest_hdr = NULL;
2716 struct ip6_frag_hdr *frag_hdr = NULL;
2717 u8_t nexth;
2718 u16_t hlen = 0;
2719
2720 LWIP_ERROR("netstat_get_udp6_sendQLen: NULL pcb received\n", (udppcb != NULL), return -1);
2721 LWIP_ERROR("netstat_get_udp6_sendQLen: NULL pbuf received\n", (udpbuf != NULL), return -1);
2722
2723 iphdr = (struct ip6_hdr *)udpbuf->payload;
2724
2725 if (!(ip6_addr_cmp(&iphdr->dest, ip_2_ip6(&udppcb->remote_ip)) &&
2726 (ip_addr_isany(&udppcb->local_ip) ||
2727 ip6_addr_cmp(&iphdr->src, ip_2_ip6(&udppcb->local_ip))))) {
2728 goto FUNC_OUT;
2729 }
2730
2731 len = IP6_HLEN;
2732 if (pbuf_header(udpbuf, (s16_t)(-(s16_t)(len)))) {
2733 goto FUNC_OUT;
2734 }
2735
2736 offset = len;
2737
2738 nexth = IP6H_NEXTH(iphdr);
2739 while (offset < udpbuf->tot_len) {
2740 if (nexth == IP6_NEXTH_NONE || nexth == IP6_NEXTH_UDP || nexth == IP6_NEXTH_UDPLITE) {
2741 break;
2742 }
2743 switch (nexth) {
2744 case IP6_NEXTH_HOPBYHOP:
2745 case IP6_NEXTH_ROUTING:
2746 nexth = *((u8_t *)udpbuf->payload);
2747 hlen = (u16_t)(8 * (1 + *((u8_t *)udpbuf->payload + 1)));
2748 break;
2749 case IP6_NEXTH_DESTOPTS:
2750 nexth = *((u8_t *)udpbuf->payload);
2751 dest_hdr = (struct ip6_dest_hdr *)udpbuf->payload;
2752 hlen = (u16_t)(8 * (1 + dest_hdr->_hlen));
2753 break;
2754 case IP6_NEXTH_FRAGMENT:
2755 frag_hdr = (struct ip6_frag_hdr *)udpbuf->payload;
2756 nexth = frag_hdr->_nexth;
2757 hlen = IP6_FRAG_HLEN;
2758 break;
2759 default:
2760 /* Unknown next_header */
2761 goto FUNC_OUT;
2762 }
2763
2764 (void)pbuf_header(udpbuf, (s16_t)(-(s16_t)hlen));
2765 offset = (u16_t)(offset + hlen);
2766 }
2767
2768 /* If the while loop test condition failed , then revert the last offset change */
2769 if (offset >= udpbuf->tot_len) {
2770 offset = (u16_t)(offset - hlen);
2771 goto FUNC_OUT;
2772 }
2773
2774 LWIP_ERROR("Transport option should be UDP", (nexth == IP6_NEXTH_UDP || nexth == IP6_NEXTH_UDPLITE), goto FUNC_OUT);
2775
2776 if (offset > iphdr->_plen) {
2777 goto FUNC_OUT;
2778 }
2779
2780 /* check if there is enough space for at least udp header available */
2781 if (udpbuf->tot_len < UDP_HLEN) {
2782 goto FUNC_OUT;
2783 }
2784
2785 udphdr = (struct udp_hdr *)udpbuf->payload;
2786 if ((ntohs(udphdr->dest) == udppcb->remote_port) && (ntohs(udphdr->src) == udppcb->local_port)) {
2787 if (ntohs(udphdr->len) > UDP_HLEN) {
2788 sendLen = ntohs(udphdr->len) - UDP_HLEN;
2789 } else {
2790 sendLen = udpbuf->tot_len - UDP_HLEN;
2791 }
2792 }
2793
2794 FUNC_OUT:
2795 (void)pbuf_header(udpbuf, (s16_t)offset); // can not cross max limit of s16_t
2796 return sendLen;
2797 }
2798 #endif
2799
2800 #if LWIP_IPV4
netstat_get_udp_sendQLen(struct udp_pcb * udppcb,struct pbuf * udpbuf)2801 int netstat_get_udp_sendQLen(struct udp_pcb *udppcb, struct pbuf *udpbuf)
2802 {
2803 int sendLen = -1;
2804 u16_t offset = 0, len;
2805 struct ip_hdr *iphdr = NULL;
2806 struct udp_hdr *udphdr = NULL;
2807
2808 LWIP_ERROR("netstat_get_udp_sendQLen: NULL pcb received\n", (udppcb != NULL), return -1);
2809 LWIP_ERROR("netstat_get_udp_sendQLen: NULL pbuf received\n", (udpbuf != NULL), return -1);
2810
2811 iphdr = (struct ip_hdr *)udpbuf->payload;
2812
2813 if (!(ip4_addr_cmp(&iphdr->dest, ip_2_ip4(&udppcb->remote_ip)) &&
2814 (ip_addr_isany(&udppcb->local_ip) ||
2815 ip4_addr_cmp(&iphdr->src, ip_2_ip4(&udppcb->local_ip))))) {
2816 goto FUNC_OUT;
2817 }
2818 #if LWIP_UDPLITE
2819 if ((IPH_PROTO(iphdr) != IP_PROTO_UDP) && (IPH_PROTO(iphdr) != IP_PROTO_UDPLITE)) {
2820 #else
2821 if (IPH_PROTO(iphdr) != IP_PROTO_UDP) {
2822 #endif
2823 goto FUNC_OUT;
2824 }
2825
2826 if ((ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK) != 0) {
2827 goto FUNC_OUT;
2828 }
2829
2830 len = (u16_t)(IPH_HL(iphdr) * 4);
2831 if (pbuf_header(udpbuf, (s16_t)(-len))) {
2832 goto FUNC_OUT;
2833 }
2834
2835 offset = (u16_t)(offset + len);
2836
2837 udphdr = (struct udp_hdr *)udpbuf->payload;
2838 if ((ntohs(udphdr->dest) == udppcb->remote_port) && (ntohs(udphdr->src) == udppcb->local_port)) {
2839 sendLen = ntohs(udphdr->len) - UDP_HLEN;
2840 }
2841
2842 FUNC_OUT:
2843 (void)pbuf_header(udpbuf, (s16_t)offset);
2844 return sendLen;
2845 }
2846 #endif
2847
2848 int netstat_tcp_recvq(struct tcp_pcb *tpcb)
2849 {
2850 unsigned int retVal = 0;
2851 #if LWIP_SO_RCVBUF
2852 struct netconn *conn = NULL;
2853 #endif
2854
2855 LWIP_ERROR("netstat_tcp_recvq: Received NULL pcb\n", (tpcb != NULL), return 0);
2856
2857 #if LWIP_SO_RCVBUF
2858 conn = (struct netconn *)tpcb->callback_arg;
2859 if (conn != NULL) {
2860 switch (conn->type) {
2861 case NETCONN_TCP:
2862 case NETCONN_RAW:
2863 #if LWIP_IPV6
2864 case NETCONN_RAW_IPV6:
2865 case NETCONN_UDP_IPV6:
2866 #endif
2867 case NETCONN_UDP:
2868 SYS_ARCH_GET(((unsigned int)conn->recv_avail), retVal); // + conn->lrcv_left
2869 break;
2870 default:
2871 retVal = 0; /* ur... very ugly, damn DHCP DNS and SNTP */
2872 }
2873 }
2874 #endif
2875
2876 return (int)retVal;
2877 }
2878
2879 int netstat_tcp_sendq(struct tcp_pcb *tpcb)
2880 {
2881 int retVal = 0;
2882 struct tcp_seg *useg = NULL;
2883
2884 LWIP_ERROR("netstat_tcp_sendq: Received NULL pcb\n", (tpcb != NULL), return 0);
2885
2886 for (useg = tpcb->unacked; useg != NULL; useg = useg->next) {
2887 retVal = retVal + useg->len;
2888 }
2889
2890 return retVal;
2891 }
2892
2893 #if LWIP_IPV6
2894 int netstat_udp_sendq6(struct udp_pcb *upcb)
2895 {
2896 int retLen = 0;
2897 int ret;
2898 int idx = 0;
2899 int i;
2900 #if LWIP_ND6_QUEUEING
2901 struct nd6_q_entry *neibq = NULL;
2902 #endif
2903
2904 LWIP_ERROR("netstat_udp_sendq6: Received NULL pcb\n", (upcb != NULL), return 0);
2905
2906 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
2907 if (neighbor_cache[i].state != ND6_NO_ENTRY) {
2908 if (ip6_addr_cmp(&upcb->remote_ip.u_addr.ip6, &neighbor_cache[i].next_hop_address)) {
2909 idx = i;
2910 break;
2911 }
2912 }
2913 }
2914 #if LWIP_ND6_QUEUEING
2915 for (neibq = neighbor_cache[idx].q; neibq != NULL; neibq = neibq->next) {
2916 ret = netstat_get_udp_sendQLen6(upcb, neibq->p);
2917 if (ret >= 0) {
2918 retLen += ret;
2919 }
2920 }
2921 #else
2922 ret = netstat_get_udp_sendQLen6(upcb, neighbor_cache[idx].q);
2923 if (ret >= 0) {
2924 retLen += ret;
2925 }
2926 #endif
2927 return retLen;
2928 }
2929 #endif
2930
2931 #if LWIP_IPV4
2932 int netstat_udp_sendq(struct udp_pcb *upcb)
2933 {
2934 int retLen = 0;
2935 int ret;
2936 int arpidx = -1;
2937 int i;
2938 #if ARP_QUEUEING
2939 struct etharp_q_entry *arpq = NULL;
2940 #endif
2941
2942 LWIP_ERROR("netstat_udp_sendq: Received NULL pcb\n", (upcb != NULL), return 0);
2943
2944 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
2945 if (arp_table[i].state != ETHARP_STATE_EMPTY) {
2946 if (ip4_addr_cmp(ip_2_ip4(&upcb->remote_ip), &arp_table[i].ipaddr)) {
2947 arpidx = i;
2948 break;
2949 }
2950 }
2951 }
2952
2953 if (arpidx >= 0) {
2954 #if ARP_QUEUEING
2955 for (arpq = arp_table[arpidx].q; arpq != NULL; arpq = arpq->next) {
2956 ret = netstat_get_udp_sendQLen(upcb, arpq->p);
2957 if (ret > 0) {
2958 retLen += ret;
2959 if (retLen <= 0) { // overflow, set rteLen = -1 to indicate
2960 retLen = -1;
2961 break;
2962 }
2963 }
2964 }
2965 #else
2966 ret = netstat_get_udp_sendQLen(upcb, arp_table[arpidx].q);
2967 if (ret > 0) {
2968 retLen += ret;
2969 if (retLen <= 0) { // overflow, set rteLen = -1 to indicate
2970 retLen = -1;
2971 }
2972 }
2973 #endif
2974 }
2975 return retLen;
2976 }
2977 #endif
2978 int netstat_netconn_recvq(const struct netconn *conn)
2979 {
2980 unsigned int retVal = 0;
2981
2982 #if LWIP_SO_RCVBUF
2983 if (conn == NULL) {
2984 return 0;
2985 }
2986
2987 switch (NETCONNTYPE_GROUP((unsigned int)(conn->type))) {
2988 case NETCONN_TCP:
2989 case NETCONN_RAW:
2990 #if PF_PKT_SUPPORT
2991 case NETCONN_PKT_RAW:
2992 #endif
2993 case NETCONN_UDP:
2994 SYS_ARCH_GET(((unsigned int)conn->recv_avail), retVal); // + conn->lrcv_left
2995 break;
2996 default:
2997 retVal = 0; /* ur... very ugly, damn DHCP DNS and SNTP */
2998 }
2999 #endif
3000 return (int)retVal;
3001 }
3002
3003 int netstat_netconn_sendq(struct netconn *conn)
3004 {
3005 int retVal = 0;
3006
3007 if (conn == NULL) {
3008 return 0;
3009 }
3010
3011 switch (NETCONNTYPE_GROUP((unsigned int)(conn->type))) {
3012 case NETCONN_TCP:
3013 retVal = netstat_tcp_sendq(conn->pcb.tcp);
3014 break;
3015 case NETCONN_RAW:
3016 retVal = 0;
3017 break;
3018 #if PF_PKT_SUPPORT
3019 case NETCONN_PKT_RAW:
3020 retVal = 0; /* always be 0 as frame send to driver directly */
3021 break;
3022 #endif
3023 case NETCONN_UDP:
3024 retVal = netstat_udp_sendq(conn->pcb.udp);
3025 break;
3026 default:
3027 retVal = 0; /* ur... very ugly, damn DHCP DNS and SNTP */
3028 }
3029
3030 return retVal;
3031 }
3032 void netstat_internal(void *ctx)
3033 {
3034 s8_t local_ip_port[64] = {0};
3035 s8_t remote_ip_port[64] = {0};
3036 struct tcp_pcb *tpcb = NULL;
3037 struct tcp_pcb_listen *lpcb = NULL;
3038 struct udp_pcb *upcb = NULL;
3039 struct raw_pcb *rpcb = NULL;
3040 s8_t *entry_buf = NULL;
3041 u32_t entry_buf_len;
3042 u32_t entry_buf_offset;
3043 struct netstat_data *ndata = (struct netstat_data *)ctx;
3044 int iRet;
3045 int recvQlen = 0;
3046 int sendQlen = 0;
3047 u_int proto;
3048 #if PF_PKT_SUPPORT
3049 u8_t netif_name[IFNAMSIZ];
3050 struct netif *netif = NULL;
3051 #endif
3052
3053 if (ndata == NULL) {
3054 return;
3055 }
3056 entry_buf = ndata->netstat_out_buf;
3057 entry_buf_len = ndata->netstat_out_buf_len;
3058 entry_buf_offset = 0;
3059
3060 if (entry_buf == NULL) {
3061 goto out;
3062 }
3063 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3064 "========== total sockets %d ====== unused sockets %d ==========\n",
3065 LWIP_CONFIG_NUM_SOCKETS, get_unused_socket_num());
3066 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3067 goto out;
3068 }
3069 entry_buf_len -= (u32_t)(iRet);
3070 entry_buf_offset += (u32_t)(iRet);
3071
3072 #if LWIP_TCP
3073 if (tcp_active_pcbs != NULL || tcp_bound_pcbs != NULL || tcp_tw_pcbs != NULL || tcp_listen_pcbs.pcbs != NULL) {
3074 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3075 "%-8s%-12s%-12s%-24s%-24s%-16s\n",
3076 "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address", "State");
3077 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3078 goto out;
3079 }
3080 entry_buf_len -= (u32_t)(iRet);
3081 entry_buf_offset += (u32_t)(iRet);
3082
3083 for (tpcb = tcp_active_pcbs; tpcb != NULL; tpcb = tpcb->next) {
3084 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1),
3085 "%s:%d", ipaddr_ntoa(&tpcb->local_ip), tpcb->local_port);
3086 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) {
3087 goto out;
3088 }
3089
3090 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1),
3091 "%s:%d", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port);
3092 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) {
3093 goto out;
3094 }
3095 if (tpcb->state == SYN_RCVD) {
3096 recvQlen = 0;
3097 sendQlen = 0;
3098 } else {
3099 recvQlen = netstat_netconn_recvq(tpcb->callback_arg);
3100 sendQlen = netstat_netconn_sendq(tpcb->callback_arg);
3101 }
3102 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3103 IP_IS_V6(&tpcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" :
3104 "%-8s%-12d%-12d%-24s%-24s%-16s\n",
3105 IP_IS_V6(&tpcb->local_ip) ? "tcp-ip6" : "tcp",
3106 recvQlen, sendQlen, local_ip_port, remote_ip_port, tcp_state_str[tpcb->state]);
3107 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3108 goto out;
3109 }
3110 entry_buf_len -= (u32_t)(iRet);
3111 entry_buf_offset += (u32_t)(iRet);
3112 }
3113
3114 /* For bound PCBs */
3115 sendQlen = 0;
3116 recvQlen = 0;
3117
3118 for (tpcb = tcp_bound_pcbs; tpcb != NULL; tpcb = tpcb->next) {
3119 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1),
3120 "%s:%d", ipaddr_ntoa(&tpcb->local_ip), tpcb->local_port);
3121 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) {
3122 goto out;
3123 }
3124
3125 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1),
3126 "%s:%d", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port);
3127 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) {
3128 goto out;
3129 }
3130
3131 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3132 IP_IS_V6(&tpcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" :
3133 "%-8s%-12d%-12d%-24s%-24s%-16s\n",
3134 IP_IS_V6(&tpcb->local_ip) ? "tcp-ip6" : "tcp",
3135 recvQlen, sendQlen, local_ip_port, remote_ip_port, tcp_state_str[tpcb->state]);
3136 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3137 goto out;
3138 }
3139 entry_buf_len -= (u32_t)(iRet);
3140 entry_buf_offset += (u32_t)(iRet);
3141 }
3142
3143 for (tpcb = tcp_tw_pcbs; tpcb != NULL; tpcb = tpcb->next) {
3144 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1),
3145 "%s:%d", ipaddr_ntoa(&tpcb->local_ip), tpcb->local_port);
3146 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) {
3147 goto out;
3148 }
3149
3150 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1),
3151 "%s:%d", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port);
3152 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) {
3153 goto out;
3154 }
3155
3156 recvQlen = netstat_netconn_recvq(tpcb->callback_arg);
3157 sendQlen = netstat_netconn_sendq(tpcb->callback_arg);
3158 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3159 IP_IS_V6(&tpcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" :
3160 "%-8s%-12d%-12d%-24s%-24s%-16s\n",
3161 IP_IS_V6(&tpcb->local_ip) ? "tcp-ip6" : "tcp",
3162 recvQlen, sendQlen, local_ip_port, remote_ip_port, tcp_state_str[tpcb->state]);
3163 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3164 goto out;
3165 }
3166 entry_buf_len -= (u32_t)(iRet);
3167 entry_buf_offset += (u32_t)(iRet);
3168 }
3169
3170 /* For listen PCBs */
3171 sendQlen = 0;
3172
3173 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
3174 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1),
3175 "%s:%d", ipaddr_ntoa(&lpcb->local_ip), lpcb->local_port);
3176 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) {
3177 goto out;
3178 }
3179
3180 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1),
3181 "%s:%d", ipaddr_ntoa(&lpcb->remote_ip), 0);
3182 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) {
3183 goto out;
3184 }
3185
3186 recvQlen = netstat_netconn_recvq(lpcb->callback_arg);
3187
3188 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3189 IP_IS_V6(&lpcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" :
3190 "%-8s%-12d%-12d%-24s%-24s%-16s\n",
3191 IP_IS_V6(&lpcb->local_ip) ? "tcp-ip6" : "tcp",
3192 recvQlen, sendQlen, local_ip_port, remote_ip_port, tcp_state_str[lpcb->state]);
3193 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3194 goto out;
3195 }
3196 entry_buf_len -= (u32_t)(iRet);
3197 entry_buf_offset += (u32_t)(iRet);
3198 }
3199 }
3200 #endif
3201 #if LWIP_UDP
3202 if (udp_pcbs != NULL) {
3203 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3204 "\n%-8s%-12s%-12s%-24s%-24s\n",
3205 "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address");
3206 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3207 goto out;
3208 }
3209 entry_buf_len -= (u32_t)(iRet);
3210 entry_buf_offset += (u32_t)(iRet);
3211
3212 for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) {
3213 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1),
3214 "%s:%d", ipaddr_ntoa(&upcb->local_ip), upcb->local_port);
3215 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) {
3216 goto out;
3217 }
3218
3219 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1),
3220 "%s:%d", ipaddr_ntoa(&upcb->remote_ip), upcb->remote_port);
3221 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) {
3222 goto out;
3223 }
3224
3225 recvQlen = netstat_netconn_recvq(upcb->recv_arg);
3226 #if LWIP_IPV6
3227 sendQlen = IP_IS_V6(&upcb->local_ip) ? netstat_udp_sendq6(upcb) : netstat_netconn_sendq(upcb->recv_arg);
3228 #else
3229 sendQlen = netstat_netconn_sendq(upcb->recv_arg);
3230 #endif
3231 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3232 IP_IS_V6(&upcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" :
3233 "%-8s%-12d%-12d%-24s%-24s%-16s\n",
3234 IP_IS_V6(&upcb->local_ip) ? "udp-ip6" : "udp",
3235 recvQlen, sendQlen, local_ip_port, remote_ip_port, " ");
3236 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3237 goto out;
3238 }
3239 entry_buf_len -= (u32_t)(iRet);
3240 entry_buf_offset += (u32_t)(iRet);
3241 }
3242 }
3243 #endif
3244
3245 #if LWIP_RAW
3246 if (raw_pcbs != NULL) {
3247 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3248 "\n%-8s%-12s%-12s%-20s%-20s%-16s%-16s\n",
3249 "Type", "Recv-Q", "Send-Q", "Local Address", "Foreign Address", "Protocol", "HDRINCL");
3250 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3251 goto out;
3252 }
3253 entry_buf_len -= (u32_t)(iRet);
3254 entry_buf_offset += (u32_t)(iRet);
3255
3256 for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) {
3257 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1),
3258 "%s", ipaddr_ntoa(&rpcb->local_ip));
3259 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) {
3260 goto out;
3261 }
3262
3263 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1),
3264 "%s", ipaddr_ntoa(&rpcb->remote_ip));
3265 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) {
3266 goto out;
3267 }
3268
3269 recvQlen = netstat_netconn_recvq(rpcb->recv_arg);
3270 sendQlen = netstat_netconn_sendq(rpcb->recv_arg);
3271
3272 proto = rpcb->protocol; // raw_proto;
3273 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3274 "%-8s%-12d%-12d%-20s%-20s%-16u%-16d\n",
3275 "raw", recvQlen, sendQlen, local_ip_port, remote_ip_port, proto, 0); // rpcb->hdrincl
3276 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3277 goto out;
3278 }
3279 entry_buf_len -= (u32_t)(iRet);
3280 entry_buf_offset += (u32_t)(iRet);
3281 }
3282 }
3283 #if PF_PKT_SUPPORT
3284 if (pkt_raw_pcbs != NULL) {
3285 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3286 "\n%-12s%-12s%-12s%-16s%-12s\n", "Type", "Recv-Q", "Send-Q", "Protocol", "netif");
3287 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3288 goto out;
3289 }
3290 entry_buf_len -= (u32_t)(iRet);
3291 entry_buf_offset += (u32_t)(iRet);
3292
3293 for (rpcb = pkt_raw_pcbs; rpcb != NULL; rpcb = rpcb->next) {
3294 recvQlen = netstat_netconn_recvq(rpcb->recv_arg);
3295 sendQlen = netstat_netconn_sendq(rpcb->recv_arg);
3296
3297 for (netif = netif_list; netif != NULL; netif = netif->next) {
3298 /* netif->ifindex and index */
3299 if (netif_get_index(netif) == rpcb->netif_idx) {
3300 (void)snprintf_s((char *)netif_name, IFNAMSIZ, IFNAMSIZ - 1, "%s", netif_get_name(netif));
3301 break;
3302 }
3303 }
3304
3305 if (netif == NULL) {
3306 (void)snprintf_s((char *)netif_name, IFNAMSIZ, IFNAMSIZ - 1, "%s", "None");
3307 }
3308
3309 proto = rpcb->protocol; // ntohs(rpcb->proto.eth_proto);
3310
3311 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1,
3312 "%-12s%-12d%-12d%-16x%-12s\n", "pkt-raw", recvQlen, sendQlen, proto, netif_name);
3313 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) {
3314 goto out;
3315 }
3316 entry_buf_len -= (u32_t)(iRet);
3317 entry_buf_offset += (u32_t)(iRet);
3318 }
3319 }
3320 #endif
3321 #endif
3322
3323 out:
3324 ndata->netstat_out_buf_updated_len = entry_buf_offset;
3325 sys_sem_signal(&ndata->cb_completed);
3326 return;
3327 }
3328
3329 u32_t osShellNetstat(int argc, const char **argv)
3330 {
3331 struct netstat_data ndata;
3332 err_t err;
3333
3334 if (argc > 0) {
3335 PRINTK("\nUsage: netstat\n");
3336 return LOS_NOK;
3337 }
3338
3339 if (tcpip_init_finish == 0) {
3340 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__);
3341 return LOS_NOK;
3342 }
3343
3344 ndata.netstat_out_buf = mem_malloc(MAX_NETSTAT_ENTRY);
3345 if (ndata.netstat_out_buf == NULL) {
3346 PRINTK("%s: no free mem\n", __FUNCTION__);
3347 return LOS_NOK;
3348 }
3349 ndata.netstat_out_buf_len = MAX_NETSTAT_ENTRY;
3350 ndata.netstat_out_buf_updated_len = 0;
3351
3352 if (sys_sem_new(&ndata.cb_completed, 0) != ERR_OK) {
3353 goto err_hand;
3354 }
3355
3356 err = tcpip_callback(netstat_internal, &ndata);
3357 if (err != ERR_OK) {
3358 sys_sem_free(&ndata.cb_completed);
3359 goto err_hand;
3360 }
3361
3362 (void)sys_arch_sem_wait(&ndata.cb_completed, 0);
3363 sys_sem_free(&ndata.cb_completed);
3364 if ((ndata.netstat_out_buf_updated_len > 0) && (ndata.netstat_out_buf_updated_len < MAX_NETSTAT_ENTRY)) {
3365 PRINTK("%s\n", (char *)(ndata.netstat_out_buf));
3366 mem_free(ndata.netstat_out_buf);
3367 return LOS_OK;
3368 }
3369
3370 err_hand:
3371 mem_free(ndata.netstat_out_buf);
3372 ndata.netstat_out_buf = NULL;
3373 (void)(argv);
3374 return LOS_NOK;
3375 }
3376 #ifdef LOSCFG_SHELL
3377 SHELLCMD_ENTRY(netstat_shellcmd, CMD_TYPE_EX, "netstat", XARGS, (CmdCallBackFunc)osShellNetstat);
3378 #endif /* LOSCFG_SHELL */
3379
3380 #define NETIF_NAME_LEN 10
3381 STATIC VOID OsShellDhclientUsage(VOID)
3382 {
3383 PRINTK("<netif name>, start dhcp for netif name\n"
3384 "-x <netif name>, stop dhcp for netif name\n"
3385 "-h | --help, print dhclient command usage\n");
3386 }
3387
3388 u32_t OsShellDhclient(int argc, const char **argv)
3389 {
3390 struct netif *netif = NULL;
3391
3392 if (argc == 0) {
3393 OsShellDhclientUsage();
3394 } else if (argc == 1) {
3395 if (strcmp(argv[0], "-h") == 0 || strcmp(argv[0], "--help") == 0) {
3396 OsShellDhclientUsage();
3397 } else {
3398 netif = netif_find(argv[0]);
3399 if (netif != NULL) {
3400 (VOID)netifapi_dhcp_start(netif);
3401 } else {
3402 PRINTK("dhclient: invalid option: %s\n", argv[0]);
3403 OsShellDhclientUsage();
3404 }
3405 }
3406 } else if (argc == 2) {
3407 if (strcmp(argv[0], "-x") == 0) {
3408 netif = netif_find(argv[1]);
3409 if (netif != NULL) {
3410 (VOID)netifapi_dhcp_stop(netif);
3411 } else {
3412 PRINTK("dhclient: invalid option: %s\n", argv[1]);
3413 OsShellDhclientUsage();
3414 }
3415 } else {
3416 PRINTK("dhclient: invalid option: %s\n", argv[0]);
3417 OsShellDhclientUsage();
3418 }
3419 } else {
3420 OsShellDhclientUsage();
3421 }
3422
3423 return 0;
3424 }
3425
3426 #ifdef LOSCFG_SHELL
3427 SHELLCMD_ENTRY(dhclient_shellcmd, CMD_TYPE_EX, "dhclient", XARGS, (CmdCallBackFunc)OsShellDhclient);
3428 #endif /* LOSCFG_SHELL */
3429
3430 #ifdef LWIP_DEBUG_TCPSERVER
3431
3432 #define MAX_SIZE 1024
3433 void tcp_access(int sockfd)
3434 {
3435 size_t n, i;
3436 ssize_t ret;
3437 char msg[MAX_SIZE] = {0};
3438 while (1) {
3439 PRINTK("waiting for recv\n");
3440 (void)memset_s(msg, MAX_SIZE, 0, MAX_SIZE);
3441 ret = recv(sockfd, msg, MAX_SIZE - 1, 0);
3442 if (ret < 0) {
3443 PRINTK("recv failed, %d.\n", (u32_t)ret);
3444 (void)closesocket(sockfd);
3445 return;
3446 } else if (ret == 0) {
3447 (void)closesocket(sockfd);
3448 PRINTK("client disconnect.\n");
3449 return;
3450 }
3451
3452 n = strlen(msg);
3453 for (i = 0; i < n; ++i) {
3454 if (msg[i] >= 'a' && msg[i] <= 'z') {
3455 msg[i] = (char)(msg[i] + ('A' - 'a'));
3456 } else if (msg[i] >= 'A' && msg[i] <= 'Z') {
3457 msg[i] = (char)(msg[i] + ('a' - 'A'));
3458 }
3459 }
3460
3461 if (send(sockfd, msg, n, 0) < 0) {
3462 PRINTK("send failed!\r\n");
3463 continue;
3464 }
3465 }
3466 }
3467
3468 u32_t osTcpserver(int argc, const char **argv)
3469 {
3470 uint16_t port;
3471 int sockfd = -1;
3472 int ret;
3473 struct sockaddr_in seraddr;
3474 struct sockaddr_in cliaddr;
3475 u32_t cliaddr_size = (u32_t)sizeof(cliaddr);
3476 int reuse, iPortVal;
3477
3478 if (tcpip_init_finish == 0) {
3479 PRINTK("tcpip_init have not been called\n");
3480 return LOS_NOK;
3481 }
3482
3483 if (argc < 1 || argv == NULL) {
3484 PRINTK("\nUsage: tcpserver <port>\n");
3485 return LOS_NOK;
3486 }
3487
3488 iPortVal = atoi(argv[0]);
3489 /* Port 0 not supported , negative values not supported , max port limit is 65535 */
3490 if (iPortVal <= 0 || iPortVal > 65535) {
3491 PRINTK("\nUsage: Invalid port\n");
3492 return LOS_NOK;
3493 }
3494
3495 port = (uint16_t)iPortVal;
3496
3497 /* removed the print of argv[1] as its accessing argv[1] without verifying argc and
3498 * argv[1] not used anywhere else */
3499 PRINTK("argv[0]:%s, argc:%d\r\n", argv[0], argc);
3500 sockfd = socket(AF_INET, SOCK_STREAM, 0);
3501 if (sockfd < 0) {
3502 PRINTK("\nUsage: create socket fail!\n");
3503 return LOS_NOK;
3504 }
3505 reuse = 1;
3506 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(reuse)) != 0) {
3507 (void)closesocket(sockfd);
3508 PRINTK("set SO_REUSEADDR failed\n");
3509 return LOS_NOK;
3510 }
3511
3512 (void)memset_s(&seraddr, sizeof(seraddr), 0, sizeof(seraddr));
3513 seraddr.sin_family = AF_INET;
3514 seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
3515 seraddr.sin_port = htons(port);
3516
3517 ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));
3518 if (ret < 0) {
3519 PRINTK("bind ip and port failed");
3520 (void)closesocket(sockfd);
3521 return LOS_NOK;
3522 }
3523
3524 ret = listen(sockfd, 5);
3525 if (ret < 0) {
3526 (void)closesocket(sockfd);
3527 PRINTK("listen failed\n");
3528 return LOS_NOK;
3529 }
3530 while (1) {
3531 PRINTK("waiting for accept\n");
3532 (void)memset_s(&cliaddr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in));
3533 ret = (int)accept(sockfd, (struct sockaddr *)&cliaddr, &cliaddr_size);
3534 if (ret < 0) {
3535 (void)closesocket(sockfd);
3536 PRINTK("Accept failed, %d\n", ret);
3537 break;
3538 }
3539 tcp_access(ret);
3540 }
3541 return LOS_NOK; // Hits Only If Accept Fails
3542 }
3543
3544 #ifdef LOSCFG_SHELL_CMD_DEBUG
3545 SHELLCMD_ENTRY(tcpserver_shellcmd, CMD_TYPE_EX, "tcpserver", XARGS, (CmdCallBackFunc)osTcpserver);
3546 #endif /* LOSCFG_SHELL_CMD_DEBUG */
3547 #endif /* LWIP_DEBUG_TCPSERVER */
3548
3549 #ifdef LWIP_DEBUG_UDPSERVER
3550 void udpserver(int argc, const char **argv)
3551 {
3552 int sockfd, fromlen;
3553 int ret, iPortVal;
3554 struct sockaddr_in seraddr;
3555 struct sockaddr_in cliaddr;
3556 size_t n, i;
3557
3558 char msg[MAX_SIZE] = {0};
3559 uint16_t port;
3560
3561 if (argc < 1) {
3562 PRINTK("\nUsage: udpserver <port>\n");
3563 return;
3564 }
3565
3566 iPortVal = atoi(argv[0]);
3567 /* Port 0 not supported , negative values not supported , max port limit is 65535 */
3568 if (iPortVal <= 0 || iPortVal > 65535) {
3569 PRINTK("\nUsage: Invalid Port\n");
3570 return;
3571 }
3572
3573 port = (uint16_t)iPortVal;
3574
3575 PRINTK("port:%d\r\n", port);
3576
3577 sockfd = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
3578 if (sockfd == -1) {
3579 PRINTK("\ncreate socket fail\n");
3580 return;
3581 }
3582
3583 (void)memset_s(&seraddr, sizeof(seraddr), 0, sizeof(seraddr));
3584 (void)memset_s(&cliaddr, sizeof(cliaddr), 0, sizeof(cliaddr));
3585 seraddr.sin_family = AF_INET;
3586 seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
3587 seraddr.sin_port = htons(port);
3588 ret = lwip_bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));
3589 if (ret < 0) {
3590 PRINTK("bind ip and port failed:%d\n", errno);
3591 (void)closesocket(sockfd);
3592 return;
3593 }
3594
3595 while (1) {
3596 ret = recvfrom(sockfd, msg, MAX_SIZE - 1, 0, (struct sockaddr *)&cliaddr, (socklen_t *)&fromlen);
3597 if (ret >= 0) {
3598 n = strlen(msg);
3599 for (i = 0; i < n; ++i) {
3600 if (msg[i] >= 'a' && msg[i] <= 'z') {
3601 msg[i] = (char)(msg[i] + 'A' - 'a');
3602 } else if (msg[i] >= 'A' && msg[i] <= 'Z') {
3603 msg[i] = (char)(msg[i] + 'a' - 'A');
3604 }
3605 }
3606 ret = sendto(sockfd, msg, n + 1, 0, (struct sockaddr *)&cliaddr, (socklen_t)fromlen);
3607 if (ret <= 0 && errno == EPIPE) {
3608 break;
3609 }
3610 } else {
3611 break;
3612 }
3613 }
3614
3615 (void)closesocket(sockfd);
3616 return;
3617 }
3618
3619 #ifdef LOSCFG_SHELL_CMD_DEBUG
3620 SHELLCMD_ENTRY(udpserver_shellcmd, CMD_TYPE_EX, "udpserver", XARGS, (CmdCallBackFunc)udpserver);
3621 #endif /* LOSCFG_SHELL_CMD_DEBUG */
3622 #endif /* LWIP_DEBUG_UDPSERVER */
3623
3624 #ifdef LWIP_DEBUG_INFO
3625 LWIP_STATIC
3626 u32_t netdebug_memp(int argc, const char **argv)
3627 {
3628 u32_t ret = LOS_OK;
3629 int type;
3630
3631 if (argc == 2) {
3632 if (!strcmp("-i", argv[1])) {
3633 debug_memp_info();
3634 } else if (!strcmp("-udp", argv[1])) {
3635 debug_memp_type_info(MEMP_UDP_PCB);
3636 } else if (!strcmp("-tcp", argv[1])) {
3637 debug_memp_type_info(MEMP_TCP_PCB);
3638 } else if (!strcmp("-raw", argv[1])) {
3639 debug_memp_type_info(MEMP_RAW_PCB);
3640 } else if (!strcmp("-conn", argv[1])) {
3641 debug_memp_type_info(MEMP_NETCONN);
3642 } else {
3643 ret = LOS_NOK;
3644 }
3645 } else if (argc == 3) {
3646 if (!strcmp("-d", argv[1])) {
3647 type = atoi(argv[2]);
3648 if (type >= 0) {
3649 debug_memp_detail(type);
3650 } else {
3651 PRINTK("Error: type < 0\n");
3652 ret = LOS_NOK;
3653 }
3654 } else {
3655 ret = LOS_NOK;
3656 }
3657 } else {
3658 ret = LOS_NOK;
3659 }
3660
3661 return ret;
3662 }
3663
3664 LWIP_STATIC
3665 u32_t netdebug_sock(int argc, const char **argv)
3666 {
3667 int idx;
3668 u32_t ret = LOS_NOK;
3669
3670 if (argc == 2) { /* 2: Number of command parameters */
3671 if (!strcmp("-i", argv[1])) {
3672 /* netdebug sock -i */
3673 for (idx = 0; idx < (int)LWIP_CONFIG_NUM_SOCKETS; idx++) {
3674 debug_socket_info(idx, 1, 0);
3675 }
3676 ret = LOS_OK;
3677 }
3678 } else if (argc == 3) { /* 3: Number of command parameters */
3679 if (!strcmp("-d", argv[1])) {
3680 idx = atoi(argv[2]); /* 2: netdebug sock -d <idx> */
3681 if (idx >= 0) {
3682 debug_socket_info(idx, 1, 1);
3683 ret = LOS_OK;
3684 } else {
3685 PRINTK("Error: idx < 0\n");
3686 }
3687 }
3688 }
3689
3690 return ret;
3691 }
3692
3693
3694 u32_t osShellNetDebug(int argc, const char **argv)
3695 {
3696 u32_t ret = LOS_NOK;
3697
3698 if (argc < 1 || argv == NULL) {
3699 goto usage;
3700 }
3701
3702 if (!strcmp("memp", argv[0])) {
3703 ret = netdebug_memp(argc, argv);
3704 if (ret != LOS_OK) {
3705 goto usage_memp;
3706 }
3707 } else if (!strcmp("sock", argv[0])) {
3708 /* netdebug sock {-i | -d <idx>} */
3709 ret = netdebug_sock(argc, argv);
3710 if (ret != LOS_OK) {
3711 goto usage_sock;
3712 }
3713 } else {
3714 goto usage;
3715 }
3716 return ret;
3717
3718 usage:
3719 /* Cmd help */
3720 PRINTK("\nUsage:\n");
3721 PRINTK("netdebug memp {-i | -d <type> | -udp | -tcp | -raw |-conn}\n");
3722 PRINTK("netdebug sock {-i | -d <idx>}\n");
3723 return LOS_NOK;
3724
3725 usage_memp:
3726 /* netdebug memp help */
3727 PRINTK("\nUsage:\n");
3728 PRINTK("netdebug memp {-i | -d <type> | -udp | -tcp | -raw |-conn}\n");
3729 return LOS_NOK;
3730
3731 usage_sock:
3732 /* netdebug sock help */
3733 PRINTK("\nUsage:\n");
3734 PRINTK("netdebug sock {-i | -d <idx>}\n");
3735 return LOS_NOK;
3736 }
3737 #endif /* LWIP_DEBUG_INFO */
3738
3739 #if defined(LOSCFG_SHELL_CMD_DEBUG) && defined(LWIP_DEBUG_INFO)
3740 SHELLCMD_ENTRY(netdebug_shellcmd, CMD_TYPE_EX, "netdebug", XARGS, (CmdCallBackFunc)osShellNetDebug);
3741 #endif /* LOSCFG_SHELL_CMD_DEBUG && LWIP_DEBUG_INFO */
3742
3743 u32_t osShellIpDebug(int argc, const char **argv)
3744 {
3745 u8_t i = 0;
3746 char acIPv6Addr[IP6ADDR_STRLEN_MAX + 1] = {0};
3747 char aclladdr[20] = {0};
3748 const char *acStates[] = {"NO_ENTRY", "INCOMPLETE", "REACHABLE", "STALE", "DELAY", "PROBE"};
3749 u8_t atleastOneEntry = 0;
3750
3751 if (!tcpip_init_finish) {
3752 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__);
3753 goto exit;
3754 }
3755
3756 /* Display prefix */
3757 PRINTK("=================\n");
3758 PRINTK("|| Prefix List ||\n");
3759 PRINTK("=================\n");
3760 PRINTK("%-50s %-16s %-20s\n", "Prefix", "netif", "validLifetime");
3761 PRINTK("---------------------------------------------------------------------------------\n");
3762 /* Display neighbour Cache Entry */
3763 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
3764 if (prefix_list[i].netif != NULL && prefix_list[i].invalidation_timer > 0) {
3765 atleastOneEntry = 1;
3766 (void)ip6addr_ntoa_r((const ip6_addr_t *)(prefix_list[i].prefix.addr), (acIPv6Addr), sizeof(acIPv6Addr));
3767 PRINTK("%-50s ", acIPv6Addr);
3768 PRINTK("%-16s ", netif_get_name(prefix_list[i].netif));
3769 PRINTK("%-20u\n", prefix_list[i].invalidation_timer);
3770 }
3771 }
3772
3773 if (!atleastOneEntry) {
3774 PRINTK("**** NO VALID PREFIXES FOUND CONFIGURED ****\n");
3775 }
3776 PRINTK("---------------------------------------------------------------------------------\n");
3777
3778 atleastOneEntry = 0;
3779
3780 PRINTK("\n\n");
3781 PRINTK("============================\n");
3782 PRINTK("|| Neighbor Cache Entries ||\n");
3783 PRINTK("============================\n");
3784 PRINTK("%-50s %-25s %-16s %-15s %-10s\n", "Neighbor", "MAC", "netif", "state", "IsRouter");
3785 PRINTK("------------------------------------------------------------"
3786 "----------------------------------------------------------\n");
3787
3788 /* Display neighbour Cache Entry */
3789 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3790 if (neighbor_cache[i].state != ND6_NO_ENTRY) {
3791 atleastOneEntry = 1;
3792 (void)ip6addr_ntoa_r((const ip6_addr_t *)(neighbor_cache[i].next_hop_address.addr), (acIPv6Addr),
3793 sizeof(acIPv6Addr));
3794 PRINTK("%-50s ", acIPv6Addr);
3795
3796 if (snprintf_s(aclladdr, sizeof(aclladdr), sizeof(aclladdr) - 1, "%02X:%02X:%02X:%02X:%02X:%02X",
3797 neighbor_cache[i].lladdr[0], neighbor_cache[i].lladdr[1], /* 0, 1, member number */
3798 neighbor_cache[i].lladdr[2], neighbor_cache[i].lladdr[3], /* 2, 3, member number */
3799 neighbor_cache[i].lladdr[4], neighbor_cache[i].lladdr[5]) < 0) { /* 4, 5, member number */
3800 return LOS_NOK;
3801 }
3802 PRINTK("%-25s ", aclladdr);
3803 PRINTK("%-16s ", netif_get_name(neighbor_cache[i].netif));
3804 PRINTK("%-15s ", acStates[neighbor_cache[i].state]);
3805 PRINTK("%-10s\n", (neighbor_cache[i].isrouter ? "Yes" : "No"));
3806 }
3807 }
3808 if (!atleastOneEntry) {
3809 PRINTK("**** NO NEIGHBOURS FOUND ****\n");
3810 }
3811 PRINTK("------------------------------------------------------------"
3812 "----------------------------------------------------------\n");
3813
3814 atleastOneEntry = 0;
3815
3816 PRINTK("\n\n");
3817 PRINTK("===============================\n");
3818 PRINTK("|| Destination Cache Entries ||\n");
3819 PRINTK("===============================\n");
3820 PRINTK("%-50s %-50s %-10s %-10s\n", "Destination", "NextHop", "PMTU", "age");
3821 PRINTK("------------------------------------------------------------"
3822 "--------------------------------------------------------\n");
3823 /* Display destination Cache Entry */
3824 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
3825 if (!ip6_addr_isany(&(destination_cache[i].destination_addr))) {
3826 atleastOneEntry = 1;
3827 (void)ip6addr_ntoa_r((const ip6_addr_t *)(destination_cache[i].destination_addr.addr), (acIPv6Addr),
3828 sizeof(acIPv6Addr));
3829 PRINTK("%-50s ", acIPv6Addr);
3830 (void)ip6addr_ntoa_r((const ip6_addr_t *)(destination_cache[i].next_hop_addr.addr), (acIPv6Addr),
3831 sizeof(acIPv6Addr));
3832 PRINTK("%-50s ", acIPv6Addr);
3833 PRINTK("%-10u ", destination_cache[i].pmtu);
3834 PRINTK("%-10u\n", destination_cache[i].age);
3835 }
3836 }
3837 if (!atleastOneEntry) {
3838 PRINTK("**** NO DESTINATION CACHE FOUND ****\n");
3839 }
3840 PRINTK("------------------------------------------------------------"
3841 "--------------------------------------------------------\n");
3842
3843 atleastOneEntry = 0;
3844 PRINTK("\n\n");
3845 PRINTK("============================\n");
3846 PRINTK("|| Default Router Entries ||\n");
3847 PRINTK("============================\n");
3848 PRINTK("%-50s %-20s %-10s\n", "Router", "invalidation_timer", "flags");
3849 PRINTK("-----------------------------------------------------------------------------\n");
3850 /* Display Default Router Cache Entry */
3851 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) {
3852 if (default_router_list[i].neighbor_entry) {
3853 atleastOneEntry = 1;
3854 (void)ip6addr_ntoa_r((const ip6_addr_t *)((default_router_list[i].neighbor_entry)->next_hop_address.addr),
3855 (acIPv6Addr), sizeof(acIPv6Addr));
3856 PRINTK("%-50s ", acIPv6Addr);
3857 PRINTK("%-20u ", default_router_list[i].invalidation_timer);
3858 PRINTK("%-10u\n", default_router_list[i].flags);
3859 }
3860 }
3861 if (!atleastOneEntry) {
3862 PRINTK("**** NO DEFAULT ROUTERS FOUND ****\n");
3863 }
3864 PRINTK("-----------------------------------------------------------------------------\n");
3865
3866 exit:
3867 return LOS_OK;
3868 }
3869
3870 #ifdef LOSCFG_SHELL_CMD_DEBUG
3871 SHELLCMD_ENTRY(ipdebug_shellcmd, CMD_TYPE_EX, "ipdebug", XARGS, (CmdCallBackFunc)osShellIpDebug);
3872 #endif
3873 #ifdef LWIP_TESTBED
3874 extern void cmd_reset(void);
3875
3876 void osShellReboot(int argc, const char **argv)
3877 {
3878 cmd_reset();
3879 }
3880
3881 #ifdef LOSCFG_SHELL_CMD_DEBUG
3882 SHELLCMD_ENTRY(reboot_shellcmd, CMD_TYPE_EX, "reboot", XARGS, (CmdCallBackFunc)osShellReboot);
3883 #endif /* LOSCFG_SHELL_CMD_DEBUG */
3884 #endif
3885
3886 #endif // LWIP_ENABLE_LOS_SHELL_CMD
3887