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