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