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