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